MySQL joins and group columns - mysql

In the following situation i need to somehow group some columns into one. I have the following query:
SELECT a.id,b.id,c.id,d.id
FROM some_table AS a
LEFT JOIN some_table AS b ON ( a.id=b.parent_id )
LEFT JOIN some_table AS c ON ( b.id=c.parent_id )
LEFT JOIN some_table AS d ON ( c.id=d.parent_id )
WHERE a.id = '22'
Results in:
+--------+--------+--------+--------+
| a.id | b.id | c.id | d.id |
+--------+--------+--------+--------+
| 22 | 24 | 25 | null |
| 22 | 381 | null | null |
| 22 | 418 | 2389 | 9841 |
+--------+--------+--------+--------+
This is an category table populated with 220,000+ rows.
I need the last id (which is not NULL). So in this case i need (25,381,9841)
What is the easiest way to achieve this?
best result should be:
+------+
| id |
+------+
| 25 |
| 381 |
| 9841 |

See COALESCE(). That's all you need!

To expand on the above answer, it seems like you need
SELECT a.id, COALESCE(d.id, c.id, b.id) AS 'id'
FROM some_table AS a
LEFT JOIN some_table AS b ON ( a.id=b.parent_id )
LEFT JOIN some_table AS c ON ( b.id=c.parent_id )
LEFT JOIN some_table AS d ON ( c.id=d.parent_id )
WHERE a.id = '22'
That would give you an output of
+------+------+
| a.id | id |
+------+------+
| 22 | 25 |
| 22 | 381 |
| 22 | 9841 |

Related

MySQL insert category rows

I'm struggling describing the problem in the Title, let alone looking for a solution that may well exist, so please excuse, or point me to the thread. I need to pad rows, so I have 4 rows per Category as in the simplified scenario below:
mysql> select * from a;
+-------+
| Num |
+-------+
| 1 |
| 2 |
| 3 |
| 4 |
+-------+
mysql> select * from b;
+----------+------+------+
| Category | Num | Data |
+----------+------+------+
| X | 2 | 10 |
| X | 3 | 12 |
| X | 4 | 8 |
| Y | 1 | 0 |
| Y | 2 | 19 |
| y | 3 | 15 |
| y | 4 | 22 |
| Z | 2 | 10 |
+----------+------+------+
The result I need is always 4 rows per category (table b will always ever have one of Num = 1, 2, 3 or 4 per category), set data = null for the padded rows:
mysql> select * from c;
+----------+------+------+
| Category | Num | Data |
+----------+------+------+
| X | 1 | NULL |
| X | 2 | 10 |
| X | 3 | 12 |
| X | 4 | 8 |
| Y | 1 | 0 |
| Y | 2 | 19 |
| y | 3 | 15 |
| y | 4 | 22 |
| Z | 1 | NULL |
| Z | 2 | 10 |
| Z | 3 | NULL |
| Z | 4 | NULL |
+----------+------+------+
I created table a artificially, as I thought it may help with the (INSERT) query?!
You can cross join table a with all available categories in table b, and then bring table b with a left join.
select
c.category,
a.num,
b.data
from a
cross join (select distinct category from b) c
left join b on b.category = c.category and b.num = a.num
You can easily turn this to an insert query to another table:
insert into c(category, num, data)
select
c.category,
a.num,
b.data
from a
cross join (select distinct category from b) c
left join b on b.category = c.category and b.num = a.num
You need left join
select a.num, b.category , b.data
from tablea a
left join tableb b on a.num = b.num
and for insert
insert into tablec (num, category, data)
select a.num, b.category , b.data
from tablea a
left join tableb b on a.num = b.num
of if need an update for the exing rows
update tablec c
inner join (
select a.num, b.category , ifnull(b.data,0)
from tablea a
left join tableb b on a.num = b.num ) t t.num= c.num and t.category = c.category
set data = t.data

How to format a FULL OUTER JOIN for more than two tables in mySQL?

I have four tables.
Table A Table B Table C Table D
+----+ +------+ +------+ +------+
| id | | id | | id | | id |
+----+ +------+ +------+ +------+
| 1 | | 2 | | 3 | | 4 |
+----+ | 4 | +------+ +------+
+------+
Is there a query that does to do a FULL OUTER JOIN such that the output is this? :
+------+------+------+------+
| id | id | id | id |
+------+------+------+------+
| 1 | NULL | NULL | NULL |
| NULL | 2 | NULL | NULL |
| NULL | NULL | 3 | NULL |
| NULL | 4 | NULL | 4 |
+------+------+------+------+
I know how to do this for 2 tables:
SELECT * FROM table_a
LEFT JOIN table_b ON table_a.res_id = table_b.res_id
UNION
SELECT * FROM table_a
RIGHT JOIN table_b ON table_a.res_id = table_b.res_id;
But I don't know how to do this for more than 2 tables.
Any help appreciated.
SQL Fiddle: http://sqlfiddle.com/#!9/58f416/1
Use a UNION subquery with all tables. Then LEFT JOIN the four tables with it:
SELECT
a.res_id as a_id,
b.res_id as b_id,
c.res_id as c_id,
d.res_id as d_id
FROM (
SELECT res_id FROM table_a
UNION
SELECT res_id FROM table_b
UNION
SELECT res_id FROM table_c
UNION
SELECT res_id FROM table_d
) u
LEFT JOIN table_a a ON a.res_id = u.res_id
LEFT JOIN table_b b ON b.res_id = u.res_id
LEFT JOIN table_c c ON c.res_id = u.res_id
LEFT JOIN table_d d ON d.res_id = u.res_id

How to COUNT and SELECT with WHERE in sql?

I have two tables user and group and also a usergroup as a link table which contains which users exist in a group.
user table
+-----+-------+
| id | name |
+-----+-------+
| U12 | John |
| U13 | Rick |
| U14 | Morty |
| U15 | Alex |
| U16 | Felix |
+-----+-------+
group table
+-----+--------+--------+
| id | name | points |
+-----+--------+--------+
| G12 | Red | 11 |
| G13 | Blue | 22 |
| G14 | Green | 55 |
| G15 | Yellow | 64 |
| G16 | Orange | 23 |
+-----+--------+--------+
usergroup table
+----+---------+----------+
| id | user_id | group_id |
+----+---------+----------+
| 1 | U12 | G12 |
| 2 | U14 | G12 |
| 3 | U15 | G12 |
| 4 | U15 | G15 |
| 5 | U12 | G13 |
+----+---------+----------+
To select the groups that a particular user is in, I can just do
SELECT group.*
FROM usergroup
INNER JOIN group
ON group.id = usergroup.group_id
WHERE usergroup.user_id = ?
But how to also simultaneously select the number of total users in the same group?
Expected Sample Output - for the groups that user U12 is in, along with total user count
+-----+------+--------+-------------+
| id | name | points | users_count |
+-----+------+--------+-------------+
| G12 | Red | 11 | 3 |
| G13 | Blue | 22 | 1 |
+-----+------+--------+-------------+
use scalar subquery
SELECT `group`.* , (select count(id) from usergroup a where a.group_id=usergroup.group_id ) as user_count
FROM usergroup
INNER JOIN `group` ON `group`.id = usergroup.group_id
WHERE usergroup.user_id = 'U12'
SELECT y.id, y.name, y.points, y.users_count
FROM usergroup x INNER JOIN
( SELECT b.id, b.name, b.points, count(a.user_id) as users_count
FROM usergroup a INNER JOIN group b
ON a.group_id = b.id
GROUP BY b.id ) AS y
ON x.group_id = y.id
WHERE x.user_id = 'U12'
SELECT a.group_id,
a.NAME,
a.points,
c.user_count
FROM group a,
usergroup b,
(SELECT x.group_id,
Count(*) AS user_count
FROM usergroup x
GROUP BY x.group_id) c
WHERE a.group_id = b.group_id
AND a.group_id = c.group_id
AND user_id = 'U12';
SELECT group.*, count(usergroup.group_id),usergroup.user_id
FROM usergroup
INNER JOIN group
ON group.id = usergroup.id
GROUP BY usergroup.group_id
Having usergroup.user_id = 'U12'
You need to use group by with having.
Check it on SQLFiddle: sqlfiddle.com/#!9/b63e13/3/0

MySQL : Find Count of Column joined from sum of different column

I have 2 tables:
table a
+----------+------------+------------+
|session_id| product_id | orders |
+----------+------------+------------+
| 1 | 11 | 0 |
| 1 | 22 | 2 |
| 1 | 34 | 1 |
| 2 | 11 | 0 |
| 3 | 43 | 0 |
| 3 | 11 | 1 |
+----------+------------+------------+
table b:
+-----------+--------------+
|product_id |category_id |
+-----------+--------------+
| 11 | 100 |
| 12 | 101 |
| 34 | 102 |
| 22 | 103 |
| 43 | 104 |
| 13 | 105 |
+-----------+--------------+
What I want is a table which consists of how many category_id were there in each session_id and also total orders placed in that session_id
+-----------+--------------------+--------+
|session_id | count(category_id) | orders |
+-----------+--------------------+--------+
| 1 | 3 | 3 |
| 2 | 1 | 0 |
| 3 | 2 | 1 |
+-----------+--------------------+--------+
I tried:
select a.session_id,count(b.category_id),sum(a.orders) from a
join table b
on a.product_id = b.product id
is this query right?
Please help me. I am a beginner
I tried with 2 methods
1)...SELECT a.session_id,COUNT(b.category_id),SUM(a.orders) FROM #a a
LEFT JOIN #b b
ON a.product_id = b.product_id GROUP BY a.session_id
GROUP BY a.Session_ID
2...) SELECT D.SESSION_ID,COUNT(CATEGORY_ID),SUM(D.ORDERS) FROM #A D
OUTER APPLY
(
SELECT CATEGORY_ID,PRODUCT_ID FROM #B B
WHERE D.PRODUCT_ID = B.PRODUCT_ID
) A
GROUP BY D.SESSION_ID
GO
Just use left join for showing all result from table A
by using only join its show the result exist in both table only.
SELECT a.session_id,COUNT(b.category_id),SUM(a.orders) FROM a
LEFT JOIN b
ON a.product_id = b.product_id GROUP BY a.`session_id`
Ofcourse you have t join tha tables, then group with the field you want.
SELECT a.Session_ID, Count(Category_ID) CategoryCount, SUM(Orders) NumberOfOrders
FROM a
LEFT OUTER JOIN b
ON a.Product_ID = b. Product ID
GROUP BY a.Session_ID
Personally, and since I don't have any info on the data structure I prefered using the LEft outer join since in case the product_id had no category, then no results of this product will show.
(unless each product should have a category, or the user needs only the products that has a category, you have to use the INNER JOIN)

fetch the unique data from two tables

I have two tables. ProductA and ProductB.
ProductA
+----+-------+
| ID | SubId |
+----+-------+
| A1 | 112 |
| B1 | 111 |
| C1 | 115 |
| D1 | 117 |
| E1 | 114 |
| F1 | 112 |
+----+-------+
ProductB
+----+-------+
| ID | SubId |
+----+-------+
| A1 | 112 |
| B1 | 111 |
| C1 | 115 |
| G1 | 001 |
| H1 | 002 |
| k1 | 003 |
+----+-------+
I want to write a query which retrieves two columns ID and SubId and displays distinct rows from ProductA table which are NOT IN ProductB. So for the above tables.
Expected Result
+----+-------+
| ID | SubId |
+----+-------+
| D1 | 117 |
| E1 | 114 |
| F1 | 112 |
+----+-------+
How can I get this done?
Query
select distinct *
from productA
where not exists
(
select null
from productB
where productA.id = productB.id
and productA.subid=productB.subid
);
Fiddle demo here
Try this query
select * from ProductA where not EXISTS(select * from productb)
SELECT <select_list>
FROM TableA A
FULL OUTER JOIN TableB B
ON A.Key==B.Key
WHERE A.Key is NULL OR B.Key IS NULL;
select * from productA a
left outer join productB b
on a.ID = b.ID
and a.subid=b.subid
where b.subid is null
and b.id is null;
Update
24 revisions later! How do you like me NOW!
http://sqlfiddle.com/#!9/954792/24
SELECT
foo.pid,
foo.sid from (
SELECT
PA.`ID` as pid,
PA.`SubId` as sid
FROM
`ProductA` as PA
LEFT JOIN
`ProductB` as PB
ON
PA.`ID` = PB.`ID`
WHERE
PB.`ID` is NULL
UNION
SELECT
P2A.`ID` as ppid,
P2A.`SubId` as ssid
FROM
`ProductA` as P2A
RIGHT JOIN
`ProductB` as P2B
ON
P2A.`ID` = P2B.`ID`
WHERE
P2B.`ID` is NULL
) as foo
Here is a good link that explains joins...
http://blog.codinghorror.com/a-visual-explanation-of-sql-joins/
You should try following,
Select * from ProductA A
Left Join ProductB B on A.ID = B.Id
Where B.Id is null or B.SubId is null
it will give you desire result.