I am trying to join two tables with respect to the max values for the values column. I would like to produce the expected results as shown below based on the max value while joining
select * from order
-------------------------
| ID | value | Name |
-------------------------
| 1 | 23 | REM |
| 2 | 0 | SER |
| 3 | 13 | MH |
| 4 | 3 | MH |
| 5 | 1 | MP |
-------------------------
select * from product
-------------------------
| ID | value | Name |
-------------------------
| 1 | 2 | ABC |
| 2 | 2 | DEG |
| 3 | 17 | XYZ |
-------------------------
Desired result:
-------------------------
| ID | Value | Name |
-------------------------
| 1 | 23 | REM |
| 2 | 2 | DEG |
| 3 | 17 | XYZ |
| 4 | 3 | MH |
| 5 | 1 | MP |
-------------------------
I have tried something like below but it's not fetching the value (NAME) from other table
SELECT
MAX(IF(a.value >b.value , a.value ,b.value )) AS Value
from order a left join product b on a.ID= b.ID
Please suggest how to get the expected result from these two tables.
Below is for BigQuery Standard SQL
#standardsql
select as value array_agg(struct(id, value, name) order by value desc limit 1)[offset(0)]
from
(
select * from `project.dataset.order`
union all
select * from `project.dataset.product`
)
group by id
with output
You can do this using a full join:
select id,
(case when p.val is null or p.val < o.val then o.val else p.val end),
(case when p.val is null or p.val < o.val then o.name else p.name end)
from product p full join
order o
using (id);
I just find this the simplest way to think about the problem.
How to select all addons which a specific user has not buyed or are no longer valid?
Assuming currentdate is 2017-03-02 17:00:00
Table1 (users):
+-----------+----------+
| id | username |
+-----------+----------+
| 1 | Walter |
| 2 | Hank |
| 3 | John |
+-----------+----------+
Table2 (buyLog):
+-----------+----------+------------+---------------------+
| id | idUsers | idItems | validUntil |
+-----------+----------+------------+---------------------+
| 1 | 1 | 1 | 2016-03-02 14:15:47 |
| 2 | 1 | 1 | 2018-03-02 14:15:47 |
| 3 | 1 | 2 | 2016-03-02 14:15:47 |
| 4 | 2 | 1 | 2018-03-02 14:15:47 |
+-----------+----------+------------+---------------------+
Table3 (addons):
+-----------+----------+
| id | name |
+-----------+----------+
| 1 | Foo |
| 2 | Bar |
| 3 | Lorem |
+-----------+----------+
Expected output for user with id 1 should be:
+-----------+----------+
| id | name |
+-----------+----------+
| 2 | Bar |
| 3 | Lorem |
+-----------+----------+
See SQL Fiddle here: http://sqlfiddle.com/#!9/16356
Where I have the most problems is to handle the validUntil in the leftJoin.
I think I have to group by during the left join to tread only the most recent validUntil record. Maybe using max(validUntil)?
This code will work
http://sqlfiddle.com/#!9/16356/1/0
SELECT
C.ID AS 'ID',
C.NAME AS 'NAME'
FROM
(SELECT
A.id AS 'ID',A.name AS 'NAME',
CASE
WHEN B.YY > '2017-03-02 17:00:00' THEN 0
ELSE 1 END AS 'Tag'
FROM
addons AS A
LEFT JOIN
(SELECT idItems AS 'XX', MAX(validUntil) AS 'YY'
FROM
buyLog
WHERE idUsers = 1 GROUP BY 1) AS B
ON
A.id = B.XX) AS C
WHERE
C.Tag = 1
My sense is that neither your explanation nor your data set and desired result are adequate to the task of explaining the problem. The following query produces the desired result, but perhaps that's just coincidence...
SELECT a.*
FROM addons a
LEFT
JOIN buylog b
ON b.iditems = a.id
AND b.validuntil > NOW()
LEFT
JOIN users u
ON u.id = b.idusers
AND u.id = 1
WHERE b.validuntil IS NULL
AND u.id IS NULL;
I have the following MySQL query:
SELECT id, name, parent_id AS pID,
(SELECT parent_id
FROM category
WHERE id = pID)
AS grandparent_id,
(SELECT parent_id
FROM category
WHERE id = grandparent_id)
AS greatgrandparent_id,
(SELECT name
FROM category
WHERE id = pID)
AS parent,
(SELECT name
FROM category
WHERE id = grandparent_id)
AS grandparent,
(SELECT name
FROM category
WHERE id = greatgrandparent_id)
AS greatgrandparent
FROM category
WHERE active = '1'
HAVING grandparent IS NOT NULL
ORDER BY grandparent_id, parent_id, sort, id ASC
When the greatgrandparent IS NULL I want it to display the grandparent value instead. Is this possible?
I've tried CASE WHEN but must be getting the syntax wrong somewhere as it keeps throwing an error.
Simple solution: IFNULL(greatgrandparent, grandparent).
You cannot have a having clause without a group by clause.
May be this code helps you.
SELECT id, name, parent_id AS pID,
case when grandparent IS NOT NULL then
(SELECT parent_id FROM category WHERE id = grandparent_id)
else
(SELECT parent_id FROM category WHERE id = pID)
end as _parent_id,
case when grandparent IS NOT NULL then
(SELECT name FROM category WHERE id = grandparent_id)
else
(SELECT name FROM category WHERE id = pID)
end AS _parent_name
FROM category WHERE active = '1'
ORDER BY grandparent_id, parent_id, sort, id ASC
I would rewrite this using left joins with aliases and coalesce.
Given this
/*
CREATE TABLE CATEGORY(ID INT, NAME VARCHAR(20), PARENT_ID INT);
TRUNCATE TABLE CATEGORY;
INSERT INTO CATEGORY VALUES
(1,'AAAA',2),(2,'AAA',3),(3,'AA',4),(4,'A',5),
(10,'BBBB',11),(11,'BBB',12)
;
*/
This code
SELECT C.ID,C.NAME,C.PARENT_ID ,
CP.NAME AS PARENTNAME,CP.PARENT_ID AS PARENT_PARENT_ID,
CG.NAME AS GRANDPARENTNAME,
CG.PARENT_ID AS GRANDPARENT_PARENT_ID,
CGG.NAME AS GREATGRANDPARENTNAME ,
CGG.PARENT_ID AS GREATGRANDPARENT_PARENT_ID
FROM CATEGORY C
LEFT JOIN CATEGORY CP ON CP.ID = C.PARENT_ID
LEFT JOIN CATEGORY CG ON CG.ID = CP.PARENT_ID
LEFT JOIN CATEGORY CGG ON CGG.ID = CG.PARENT_ID
ORDER BY C.ID;
Results in
+------+------+-----------+------------+------------------+-----------------+-----------------------+----------------------+----------------------------+
| ID | NAME | PARENT_ID | PARENTNAME | PARENT_PARENT_ID | GRANDPARENTNAME | GRANDPARENT_PARENT_ID | GREATGRANDPARENTNAME | GREATGRANDPARENT_PARENT_ID |
+------+------+-----------+------------+------------------+-----------------+-----------------------+----------------------+----------------------------+
| 1 | AAAA | 2 | AAA | 3 | AA | 4 | A | 5 |
| 2 | AAA | 3 | AA | 4 | A | 5 | NULL | NULL |
| 3 | AA | 4 | A | 5 | NULL | NULL | NULL | NULL |
| 4 | A | 5 | NULL | NULL | NULL | NULL | NULL | NULL |
| 10 | BBBB | 11 | BBB | 12 | NULL | NULL | NULL | NULL |
| 11 | BBB | 12 | NULL | NULL | NULL | NULL | NULL | NULL |
+------+------+-----------+------------+------------------+-----------------+-----------------------+----------------------+----------------------------+
and this code
SELECT C.ID,C.NAME,C.PARENT_ID ,
CP.NAME AS PARENTNAME,CP.PARENT_ID AS PARENT_PARENT_ID,
COALESCE(CG.NAME,CP.NAME) AS GRANDPARENTNAME,
COALESCE(CG.PARENT_ID,CP.PARENT_ID) AS GRANDPARENT_PARENT_ID,
COALESCE(CGG.NAME,CG.NAME) AS GREATGRANDPARENTNAME ,
COALESCE(CGG.PARENT_ID,CG.PARENT_ID) AS GREATGRANDPARENT_PARENT_ID
FROM CATEGORY C
LEFT JOIN CATEGORY CP ON CP.ID = C.PARENT_ID
LEFT JOIN CATEGORY CG ON CG.ID = CP.PARENT_ID
LEFT JOIN CATEGORY CGG ON CGG.ID = CG.PARENT_ID
ORDER BY C.ID
results in
+------+------+-----------+------------+------------------+-----------------+-----------------------+----------------------+----------------------------+
| ID | NAME | PARENT_ID | PARENTNAME | PARENT_PARENT_ID | GRANDPARENTNAME | GRANDPARENT_PARENT_ID | GREATGRANDPARENTNAME | GREATGRANDPARENT_PARENT_ID |
+------+------+-----------+------------+------------------+-----------------+-----------------------+----------------------+----------------------------+
| 1 | AAAA | 2 | AAA | 3 | AA | 4 | A | 5 |
| 2 | AAA | 3 | AA | 4 | A | 5 | A | 5 |
| 3 | AA | 4 | A | 5 | A | 5 | NULL | NULL |
| 4 | A | 5 | NULL | NULL | NULL | NULL | NULL | NULL |
| 10 | BBBB | 11 | BBB | 12 | BBB | 12 | NULL | NULL |
| 11 | BBB | 12 | NULL | NULL | NULL | NULL | NULL | NULL |
+------+------+-----------+------------+------------------+-----------------+-----------------------+----------------------+----------------------------+
This is a followup question to the excellent answer:
SQL Select only rows with Max Value on a Column
SQLFiddle http://sqlfiddle.com/#!2/3077f/2
Table "yourtable":
| id | val | ignore | content |
-------------------------------
| 1 | 10 | 0 | A |
| 1 | 20 | 0 | B |
| 1 | 30 | 1 | C |
| 2 | 40 | 0 | D |
| 2 | 50 | 0 | E |
| 2 | 60 | 1 | F |
When looking for max val per id, following sql is used:
select yt1.*
from yourtable yt1
left outer join yourtable yt2
on (yt1.id = yt2.id and yt1.val < yt2.val )
where yt2.id is null;
So the result will be in this case
| id | val | ignore | content |
-------------------------------
| 1 | 30 | 1 | C |
| 2 | 60 | 1 | F |
The Question is how to filter out by column "ignore" when it's =1 so the result will be
| id | val | ignore | content |
-------------------------------
| 1 | 20 | 0 | B |
| 2 | 50 | 0 | E |
You need to put the condition both in the subquery and the outer query:
select yt1.*
from yourtable yt1 left outer join
yourtable yt2
on yt1.id = yt2.id and yt1.val < yt2.val and yt2.ignore <> 1
where yt2.id is null and yt1.ignore <> 1;
You can simply add another condition and yt1.ignore <> 1, as below:
select yt1.*
from yourtable yt1
left outer join yourtable yt2
on (yt1.id = yt2.id and yt1.val < yt2.val )
where yt2.id is null and yt1.ignore <> 1;
If I make a selection from my MySQL table like:
SELECT * FROM mytable ORDER BY country_id, category
I get the following table:
+------------+----------+-------+
| country_id | category | order |
+------------+----------+-------+
| 1 | A | 0 |
| 1 | B | 0 |
| 1 | F | 0 |
| 3 | A | 0 |
| 3 | C | 0 |
| 5 | B | 0 |
| 5 | L | 0 |
| 5 | P | 0 |
+------------+----------+-------+
What I would like to do is update the order column so that the value of that column is the order of that row for it's country_id. In other words the final table should look like this:
+------------+----------+-------+
| country_id | category | order |
+------------+----------+-------+
| 1 | A | 1 |
| 1 | B | 2 |
| 1 | F | 3 |
| 3 | A | 1 |
| 3 | C | 2 |
| 5 | B | 1 |
| 5 | L | 2 |
| 5 | P | 3 |
+------------+----------+-------+
If I use the original query given at the top in a subquery, that would give me the correct order but I can't figure out how to iterate through the table and suspect I thinking about it wrongly.
How can I get this result?
Many thanks
Try to use this query -
UPDATE mytable t1
JOIN (
SELECT t1.country_id, t1.category, COUNT(*) `order`
FROM mytable t1
LEFT JOIN mytable t2
ON t2.country_id = t1.country_id AND t2.category <= t1.category
GROUP BY
t1.country_id, t1.category
) t2
ON t1.country_id = t2.country_id AND t1.category = t2.category
SET t1.`order` = t2.`order`
As an aside note, you can remove order field from the table because this can calculated this on the fly.