Can we combine VALUES and SELECT queries in MySQL - java

I am trying to insert data into a table. That table has 6 attributes, 2 of its own and 4 foreign keys.
Now I write a query like this:
insert into ***bus***
values ( 4 , 45 , (**select** **bus_driver**.id , **conductor**.id , **trip_location**.trip_id , **bus_route**.route_id
**from bus_driver , conductor , trip_location , bus_route**));
And its giving me an error like:
Error Code: 1241. Operand should contain 1 column(s)
What should I change in my query

You need to remove the values clause and just put the select straight after the table and column names of the insert clause like below :
insert into bus(column1, column2 ........)
select 4 , 45 , bus_driver.id , conductor.id , trip_location.trip_id ,
bus_route.route_id from bus_driver , conductor , trip_location , bus_route;

It's not clear what you're trying to do. It looks like you're going to end up with a lot of rows inserted into your bus table depending on the data in the other tables you're selecting from.
If you run only the select statement, see what you get for results:
select bus_driver.id, conductor.id, trip_location.trip_id, bus_route.route_id
from bus_driver, conductor, trip_location, bus_route
Then add 4, 45 in front of all those rows. That's what you'll be inserting into the bus table.
You may be looking to do something more like:
insert into bus (column1, column2, column3, column4, column5, column6)
select 4, 45, bus_driver.id, conductor.id, trip_location.trip_id, bus_route.route_id
from bus_driver, conductor, trip_location, bus_route
where bus_driver.column? = ?
and conductor.column? = ?
...
And the where clauses would be constructed such that only one record is returned for each table. It depends on what you're trying to do though. There may be situations where you want more than one record from the selected tables, which would end up inserting multiple records into the bus table

Related

Insert if not exist and update certain values if it does

I'm using JDBI3 (and would like to use #SQLUpdate) and an Oracle DB.
I want to insert an item with 4 columns into the table if it does not exist, if it does exist I want to instead update 3 of the 4 values of the item. If it wasn't Oracle I would've used some ON DUPLICATE_KEY logic but that does not exist in Oracle. I read some things about using Merge but the Queries seemed really wonky for what I was trying to do. Any tips on what to look for?
Additional question: If it is Merge I should use (with some form of sub queries I assume), how does the query affect performance? I think this database is quite write heavy.
MERGE INTO device db USING (SELECT 'abc' AS col1, 'bcd' as col2, 'cde' as col3, 'def' as col4 FROM DUAL) input
on (db.col1 = input.col1 AND db.col2= input.col2)
WHEN MATCHED THEN UPDATE
SET db.col4 = input.col4
WHEN NOT MATCHED THEN INSERT
(db.col1, db.col2, db.col3, db.col4)
VALUES (input.col1, input.col2, input.col3, input.col4)
Merge it is. Performs well.
Dummy example based on your description:
merge into target_table a
using source_table b
on (a.id = b.id)
when matched then update set
a.name = b.name,
a.job = b.job,
a.sal = b.sal
when not matched then
insert (id, name, job, sal)
values (b.id, b.name, b.job, b.sal);

MySql count of rows and insert into the table that count

I have a scenario where i need to take count of rows in mysql table for the current branch(in that table we are store branch) and insert the count of rows with other details into the same table. But the problem is when two or more concurrent users try to insert from the same branch at the same time the count is same for all the users, but for me the insert should not happ for the other user(s) until i read the count and insert that one user request . Is there any way the locking works for this and any example would be helpful(All i need to do this in MySql store procedure)
Edit : Sorry, I cant share the working code but i can write example here
My table structure is here
id name branchid count
1 abc 1 1
2 xyz 1 2
3 abcd 2 1
4 wxyz 2 2
Here am taking count of rows from the above table for given branch(ex : 1) and inserting the row with that calculated count
Ex :
set #count = (select count(id) from tbl where branchid = 1);
later
insert into tbl(id, name, branchid, count)
values(5, 'abcd', 1, #count)
This works great provided if only one user access this from one branch , but if more than one user from same branch try to access this at exact same time the
#count
is duplicating for the branch users.
Why not just do it in one query:
insert into tbl(id, name, branchid, count)
select 5, 'abcd', 1, count(*)
from from tbl
where branchid = 1;

How to write this query with hibernate using mysql DB

I am trying to select one row from all 3 tables. The tables have the same structure, 4 columns, "code", "airportname", "latitude", "longitude".
The query I am trying to write is:
select
finnairroute.code,finnairroute.airportname,finnairroute.latitude,finnairroute.longitude,lhroute.airportname,lhroute.latitude,lhroute.longitude,sasroute.code,sasroute.airportname,sasroute.latitude,sasroute.longitude
FROM frs.sasroute, frs.finnairroute,frs.lhroute where
sasroute.code="BER" or finnairroute.code ="BER" or lhroute.code
="BER";
Tested with Mysql workbench and I got this result:
How should I write the query in order to get one single row that has all the info for "BER"?
Many thanks!
You can try something like this:
SELECT finnairroute.*,lhroute.*,sasroute.* FROM DUAL
LEFT OUTER JOIN finnairroute ON (finnairroute.code='BER')
LEFT OUTER JOIN lhroute ON (lhroute.code='BER')
LEFT OUTER JOIN sasroute ON (sasroute.code='BER')
The thing is that you will always get one row, even if the code is in none of the table. You need to test whether finnairroute.code, lhroute.code and sasroute.code are null or not.
Another way to approach the problem:
SELECT 'finnair' as company,code,airportname,latitude,longitude FROM finnairroute WHERE code='BER'
UNION SELECT 'lh' as company,code,airportname,latitude,longitude FROM lhroute WHERE code='BER'
UNION SELECT 'sas' as company,code,airportname,latitude,longitude FROM sasroute WHERE code='BER'
This gives you between zero and three rows, depending on what tables contain the code 'BER'. An additional column, 'company' tels you which table contains each row.

Is it possible to get partitioned data using SQL?

I have a RDBMS table with a column BIGINT type and values are not sequential. I have a java program where I want each thread to get data as per PARTITION_SIZE i.e. I want a pair of column values like after doing ORDER BY on result,
Column_Value at Row 0 , Column_Value at Row `PARTITION_SIZE`
Column_Value at Row `PARTITION_SIZE+1` , Column_Value at Row `2*PARTITION_SIZE`
Column_Value at Row `2*PARTITION_SIZE+1` , Column_Value at Row `3*PARTITION_SIZE`
Eventually, I will pass above value ranges in a SELECT query's BETWEEN clause to get divided data for each thread.
Currently, I am able to do this partitioning via Java by putting all values in a List ( after getting all values from DB ) and then getting values at those specific indices - {0,PARTITION_SIZE},{PARTITION_SIZE+1,2*PARTITION_SIZE} ..etc but problem there is that List might have millions of records and is not advisable to store in memory.
So I was wondering if its possible to write such a query using SQL itself which would return me those ranges like below?
row-1 -> minId , maxId
row-2 -> minId , maxId
....
Database is DB2.
For example,
For table column values 1,2,12,3,4,5,20,30,7,9,11 ,result of SQL query for a partition size =2 should be {1,2},{3,4} ,{5,7},{9,11},{12,20},{30} .
In my eyes the mod() function would solve your problem and you could choose a dynamic number of partitions with it.
WITH numbered_rows_temp as (
SELECT rownumber() over () as rownum,
col1,
...
coln
FROM table
ORDER BY col1)
SELECT * FROM numbered_rows_temp
WHERE mod(rownum, <numberofpartitions>) = 0
Fill in the appropriate and change the result from 0 to - 1 in your queries.
Michael Tiefenbacher's answer is probably more useful, as it avoids an extra query, but if you do want to determine ID ranges, this might work for you:
WITH parms(partition_size) AS (VALUES 1000) -- or whatever
SELECT
MIN(id), MAX(id),
INT(rn / parms.partition_size) partition_num
FROM (
SELECT id, ROW_NUMBER() OVER (ORDER BY id) rn
FROM yourtable
) t , parms
GROUP BY INT(rn / parms.partition_size)

Combine two resultset from different table

My Requirement is to display some of the columns in one table and some of the columns in another table in an html table. Though it has same coloumn id , value will be different. So, I cannot match this two. My query is as follows:
SELECT time_stamp,queryresultset FROM table1 d WHERE dID = 'CP009'
AND d.time_stamp >'2011-05-01 00:00:00' AND d.time_stamp < '2011-05-01 05:00:00'
order by time_stamp
UNION ALL
SELECT time_stamp,cpuutil FROM table2 h WHERE hID='HS002'
AND h.time_stamp >'2011-05-01 00:00:00' AND h.time_stamp < '2011-05-01 05:00:00'
order by time_stamp
So, the time_stampe here I'm getting will vary just in milliseconds for both the table. But, I want it in one resultset. Though the time value varies in millisecones between the table, the number of rows will be equal. So, I have to bring this in a single resultset. I don't know whether it is possible to handle in sql query. Or I may have to try in java coding? Please guide me. Following is my sample html table.
----------------------------------------------------
Time_stamp Cpuutil Queryresultset
----------------------------------------------------
2011-03-09 12:00:00 2.3 9.8
2011-03-09 12:15:00 5.3 4.5
2011-03-09 12:30:00 4.3 9.3
2011-03-09 12:45:00 2.3 9.2
I am afraid, I have difficulties with understanding your question, but it seems to me, you are looking for something as:
SELECT table1.time_stamp t1, table1.queryresultset, table2.time_stamp t2, table2.cpuutil
FROM table1 , table2
WHERE ABS(t1-t2)<100
AND t1 >'2011-05-01 00:00:00'
AND t1 < '2011-05-01 05:00:00'
ORDER by t1
Another posibility:
`SELECT column list
FROM table1
INNER JOIN table2
ON table1.col1=table2.col2
WHERE criteria
ORDER BY column list `
Have a nice day.
This sounds like a database conception mistake. If your two tables are linked logically, they should have a physical connector. If you can refactor your database model, the best solution is to add a table table0 holding the common factors between the two tables (or just an autoincrement id), and then to add an external key to table1 and table2. You need to insert a row into table0 first, then to insert a row into table1 and one into table2 using table0's key as an external key.
If you can't refactor the tables, that's too bad. Anyway, the easiest way to do what you want is to write java code:
Open resultset1 from table 1
Open resultset2 from table 2
While resultset1 is not empty
fetch row1 from resultset1
fetch row2 from resultset2
generate html
Close resultsets
Done!
But this way is wrong and you will get problems as you advance further in your project.
Thanks for your responses. So I found out the query. It's working now.
SELECT a.cpuutil,a.hostid,a.time_stamp, b.queryresultset, b.time_stamp AS tm
FROM table1 a, table2 b
WHERE a.hID = 'hs002' AND b.dID='cp011'
AND SUBSTR(a.time_Stamp,1,15) = SUBSTR(b.time_stamp,1,15)
AND a.time_stamp > '2011-05-10 00:00:00'
AND a.time_stamp < '2011-05-10 14:00:00'

Categories