Query for merging two table data - mysql

I have two tables :
stock in
Id---date---Itemname----stockInqty
1 --12/12/2014 ----testitem----12
2 --13/12/2014 ----testitem11----20
and stock out
Id--date--Itemname---stockOutqty
1 --12/12/2014 ----testitem----7
2 --14/12/2014 ----testitem11----15
I need a combined result of testitem record between two date period in the order of
date----itemname----stockInqty----stockOutqty
12/12/2014--testitem---12----7
13/12/2014--testitem---20----Nil
13/12/2014--testitem---NIL----15

You could use FULL JOIN if it was not MySQL, so you should use LEFT/RIGHT JOIN with UNION :
SELECT t1.`date`
, t1.itemname
, t1.stockInqty AS stockInqty
, t2.stockInqty AS stockOutqty
FROM tbl1 t1 LEFT JOIN tbl2 t2 ON t1.`date` = t2.`date`
AND t1.itemname = t2.itemname
UNION
SELECT t2.`date`
, t2.itemname
, t1.stockInqty AS stockInqty
, t2.stockInqty AS stockOutqty
FROM tbl1 t1 RIGHT JOIN tbl2 t2 ON t1.`date` = t2.`date`
AND t1.itemname = t2.itemname

Try this:
SELECT *
FROM StockA
LEFT OUTER JOIN StockB
ON StockA.dataItem = StockB.dataItem
UNION
SELECT *
FROM StockB
LEFT OUTER JOIN StockA
ON StockA.dataItem = StockB.dataItem
You must use a FULL OUTER JOIN operation
In MySql FULL OUTER JOIN can emulate with two LEFT OUTER JOIN in UNION

Related

LEFT OUTER JOIN with OR versus UNION

Are there significant performance considerations between using UNION versus LEFT OUTER JOIN with OR in the WHERE clause?
What is the difference between these two queries?
Is it often better to use LEFT OUTER JOINs instead of a UNION?
My reason for asking is I actually need to do an INSERT, and can't use a UNION even if I wanted to.
SELECT t.foo
FROM t
INNER JOIN t1 t1.t_id=t.id
WHERE t1.id IN (1,2,3)
UNION
SELECT t.foo
FROM t
INNER JOIN t2 t2.t_id=t.id
INNER JOIN t2a ON t2a.t2_id=t2.id
WHERE t2a.id IN (1,2,3)
UNION
SELECT t.foo
FROM t
INNER JOIN t3 t3.t_id=t.id
INNER JOIN t3a ON t3a.t3_id=t3.id
WHERE t3a.id IN (1,2,3);
SELECT DISTINCT t.foo
FROM t
LEFT OUTER JOIN t1 t1.t_id=t.id
LEFT OUTER JOIN t2 t2.t_id=t.id
LEFT OUTER JOIN t2a ON t2a.t2_id=t2.id
LEFT OUTER JOIN t3 t3.t_id=t.id
LEFT OUTER JOIN t3a ON t3a.t3_id=t3.id
WHERE t1.id IN (1,2,3) OR t2a.id IN (1,2,3) OR t3a.id IN (1,2,3);
UPDATE t
LEFT OUTER JOIN t1 t1.t_id=t.id
LEFT OUTER JOIN t2 t2.t_id=t.id
LEFT OUTER JOIN t2a ON t2a.t2_id=t2.id
LEFT OUTER JOIN t3 t3.t_id=t.id
LEFT OUTER JOIN t3a ON t3a.t3_id=t3.id
SET t.foo="bar"
WHERE t1.id IN (1,2,3) OR t2a.id IN (1,2,3) OR t3a.id IN (1,2,3);
As with many performance questions, you should test the results on your data and your systems. The union and left joins are doing very different things -- and which is better probably depends on features of your data, available indexes, and other considerations.
However, you can use the union method in update. You just need a subquery:
update t join
(select t.id, t1.foo . . .
union . . .
select t.id, t2.foo
) tt
on t.id = tt.id
set t.foo = 'foo'
where . . .;
You might also find it more efficient to use the union approach but to break the update into multiple separate update statements.
You can use UNION in inserts.
INSERT INTO `table`
SELECT * FROM
(
SELECT '1'
UNION
SELECT '2'
) x
Same goes for updates:
UPDATE `table1` t1
JOIN (
SELECT '1' as col1
UNION
SELECT '2'
) x ON x.col1 = t1.colX
SET t1.whateverColumn = "someValue"
As for performance, it's mainly down to indexes. Both can be fast, both can be slow. If you're indexing them correctly, you shouldn't see big differences between the two.

Union on simple MySQL recursion

Is there a way to do a UNION between the LEFT JOIN lines, so that the results are not in a separate columns (lev1, lev2, lev3 and lev4), but in a single column (i.e. "ItemNo")?
Here's the MySQL query:
SELECT t1.ItemID AS lev1, t2.ItemID as lev2, t3.ItemID as lev3, t4.ItemID as lev4
FROM TableOfRelations AS t1
LEFT JOIN TableOfRelations AS t2 ON t2.ParentItemID = t1.ItemID
LEFT JOIN TableOfRelations AS t3 ON t3.ParentItemID = t2.ItemID
LEFT JOIN TableOfRelations AS t4 ON t4.ParentItemID = t3.ItemID
WHERE t1.ParentItemID = (SELECT ID FROM TableOfItems WHERE ItemID = 3599);
EDIT:
Here is a sample of result I am looking for:
ItemID ParentItemID JoinedDescription1 JoinedDescription2
3599 NULL MyString1A MyString1B
35 3599 MyString35A MyString35B
168 3599 MyString168A MyString168B
192 168 MyString192A MyString192B
238 3599 MyString238A MyString238B
266 168 MyString266A MyString266B
This result will be used for filling up a TreeView using VB.NET. Also the "JoinedDescriptions" are yet to be joined from a different table according to ItemID, but I think I can handle that easily once I get the basic table correctly.
Important note: Those selected lines are only belonging to one item (root item "3599" in this example), meaning it's only few lines out of thousands. Some recursion examples presume that all the table lines are used in the query, which is not my case.
No, there's not really a way to do a UNION between the LEFT JOIN operations.
But you can use the resultset from your query to get the result you want, by turning your query into an inline view.
Here's one way:
SELECT u.i AS lev
, CASE u.i
WHEN 1 THEN t.lev1
WHEN 2 THEN t.lev2
WHEN 3 THEN t.lev3
WHEN 4 THEN t.lev4
END AS levItemID
FROM ( SELECT 1 AS i
UNION ALL SELECT 2
UNION ALL SELECT 3
UNION ALL SELECT 4
) u
CROSS
JOIN ( SELECT t1.ItemID AS lev1
, t2.ItemID AS lev2
, t3.ItemID AS lev3
, t4.ItemID AS lev4
FROM TableOfItems t0
JOIN TableOfRelations t1
ON t1.ParentItemID = t0.id
LEFT
JOIN TableOfRelations t2
ON t2.ParentItemID = t1.ItemID
LEFT
JOIN TableOfRelations t3
ON t3.ParentItemID = t2.ItemID
LEFT
JOIN TableOfRelations t4
ON t4.ParentItemID = t3.ItemID
WHERE t0.ItemID = 3599
) t
Note: this is really more of a UNION ALL operation, it doesn't remove duplicates, it returns NULL values, and it returns the level of the parent.
You can tweak the query to get the results you want. If you don't care about the level number, remove the u.i from the SELECT list.
To remove duplicates, you can either add the DISTINCT keyword following SELECT, or add a GROUP BY clause. To eliminate NULL values, you can add a HAVING levItemID IS NOT NULL clause, etc.
I believe you are looking for concatenating strings.
See the Mysql Documentation on Concat:
http://dev.mysql.com/doc/refman/5.0/en/string-functions.html#function_concat
How about using a query as below.
select t1.ItemID as ItemNo
LEFT JOIN TableOfRelations AS t2 ON t2.ParentItemID = t1.ItemID
LEFT JOIN TableOfRelations AS t3 ON t3.ParentItemID = t2.ItemID
LEFT JOIN TableOfRelations AS t4 ON t4.ParentItemID = t3.ItemID
WHERE t1.ParentItemID = (SELECT ID FROM TableOfItems WHERE ItemID = 3599)
UNION
select t2.ItemID as ItemNo
LEFT JOIN TableOfRelations AS t2 ON t2.ParentItemID = t1.ItemID
LEFT JOIN TableOfRelations AS t3 ON t3.ParentItemID = t2.ItemID
LEFT JOIN TableOfRelations AS t4 ON t4.ParentItemID = t3.ItemID
WHERE t1.ParentItemID = (SELECT ID FROM TableOfItems WHERE ItemID = 3599)
UNION
select t3.ItemID as ItemNo
LEFT JOIN TableOfRelations AS t2 ON t2.ParentItemID = t1.ItemID
LEFT JOIN TableOfRelations AS t3 ON t3.ParentItemID = t2.ItemID
LEFT JOIN TableOfRelations AS t4 ON t4.ParentItemID = t3.ItemID
WHERE t1.ParentItemID = (SELECT ID FROM TableOfItems WHERE ItemID = 3599)
UNION
select t4.ItemID as ItemNo
LEFT JOIN TableOfRelations AS t2 ON t2.ParentItemID = t1.ItemID
LEFT JOIN TableOfRelations AS t3 ON t3.ParentItemID = t2.ItemID
LEFT JOIN TableOfRelations AS t4 ON t4.ParentItemID = t3.ItemID
WHERE t1.ParentItemID = (SELECT ID FROM TableOfItems WHERE ItemID = 3599)
Assuming you mean that you want the itemID on leaf nodes (I see no mention of itemNo in your query)....
SELECT
IFNULL(t4.ItemID, IFNULL(t3.ItemID, IFNULL(t2.ItemID, t1.ItemId))
(+remainder of your query)

select query using leftjoin doesnt work

I want to left join this query but it does not seem to work
select *,(SELECT datediff(t1.expirydate,CURDATE())as daysleft
from tbl1 t1,
left join tbl2 t2 on (t1.mid=t2.mid and t1.pid=t2.pid and t1.uid=3)
you have an error in your SQL syntax;
right syntax to use near 'left join tbl2 t2 on (t1.mid=t2.mid and t1.pid=t2.p' at line 3
Please let me know where am i wrong
here am joining 3 table but doesnt work
SELECT t1.*, t2.*,t3.* datediff(t1.expirydate, CURDATE()) AS daysleft FROM tbl1 t1 left join
tbl2 t2 on t1.mid = t2.mid and t1.pid = t2.pid left join tbl3 t3 on t3.pid = t2.pid where t1.uid=3
for knw 3 table but the i get syntax error
You don't put a comma between joins.
SELECT t1.*, t2.*, datediff(fsp.expirydate, CURDATE()) AS daysleft
FROM tbl1 t1
left join tbl2 t2 on t1.mid = t2.mid and t1.pid = t2.pid
cross join fsp
where t1.uid = 3
You also shouldn't put the t1.uid = 3 condition in the ON clause. ON should only contain conditions that relate the two tables, and in the case of LEFT JOIN it can also include conditions on the table you're joining with (t2 in this case).
No comma after "t1" on line 2.
Also I don't think you can do "*," on line 1, you need to either do "SELECT *" or "SELECT column, column2"
You have Used Comma (,) before Left Join It's not correct Synatx
Try this
select t1.*,(SELECT datediff(fsp.expirydate,CURDATE())as daysleft
from tbl1 t1
left join tbl2 t2 on (t1.mid=t2.mid and t1.pid=t2.pid and t1.uid=3)
Join Syntax

MySql Select data from multiple tables

This is my current query:
SELECT * FROM images T
JOIN boxes_items T2
ON T.ITEM_ID = T2.ITEM_PARENT_ID
WHERE T2.ITEM_ID = '$image_id'
I also need to Select all from a table named 'boxes' where the box_id is taken from boxes_items.
How to add this to the query?
try this
SELECT T.* , T2.* , T3.* FROM images T
JOIN boxes_items T2 ON T.ITEM_ID = T2.ITEM_PARENT_ID
JOIN boxes T3 ON T3.box_id = t2.box_id
WHERE T2.ITEM_ID = '$image_id'
SELECT *
FROM images T
JOIN boxes_items T2 ON T.ITEM_ID = T2.ITEM_PARENT_ID
JOIN boxes AS b ON b.box_id = t2.box_id
WHERE T2.ITEM_ID = '$image_id'
You really shouldn't use *, it can get you into more trouble than it is worth. Especially since you have more than one table in your query.
Anyway:
Select T.*, T2.*, T3.*
from images T
join boxes_items T2 on T.ITEM_ID = T2.ITEM_PARENT_ID
join boxes T3 on T3.box_id = T2.box_id
WHERE T2.ITEM_ID = '$image_id'

select from 2 tables with for statement in sql

i have 2 table and want to select data from them
table 1 :
id
name
table 2
id
name
table1.id
and i want a query to make this resualt:
table1.id
table1.name
count(table2.id)
this is simple and solved by this way :
SELECT
c.id as corridor_id,
c.name as corridor_name,
(SELECT COUNT( r.id ) FROM rooms AS r WHERE r.corridorid = c.id ) as room_count
FROM corridors AS c
now if i add another table like this :
table3
id
name
table2.id
and want a query like this :
table1.id
table1.name
count(table2.id)
count(table3.id)
idk how can i do such as this query, but if there is a way i'll be happy to find it, many tnx
You'll want to join them all together, and then Group them along these lines:
SELECT
t1.Id,
t1.Name,
Count(t2.Id) AS T2Count,
Count(t3.Id) AS T3Count
FROM table1 t1
JOIN table2 t2
ON t1.Id = t2.table1_id
JOIN table3 t3
ON t2.id = t3.table2_id
GROUP BY t1.Id, t1.Name
You don't need nested SELECT statement here. You can do it by grouping and to avoid double-counting you would want DISTINCT keyword:
SELECT
c.id as corridor_id,
c.name as corridor_name,
COUNT(DISTINCT r1.id),
COUNT(DISTINCT r2.id)
FROM
corridors c
JOIN rooms r ON r.corridorid = c.id
JOIN rooms2 r2 ON r2.corridorid = c.id
GROUP BY c.id
If you want to properly treat missing values (0 counts) you can also do this:
SELECT
c.id as corridor_id,
c.name as corridor_name,
IFNULL(COUNT(DISTINCT r1.id), 0),
IFNULL(COUNT(DISTINCT r2.id), 0)
FROM
corridors c
LEFT JOIN rooms r ON r.corridorid = c.id
LEFT JOIN rooms2 r2 ON r2.corridorid = c.id
GROUP BY c.id