I have 4 different tables; each have their own DATETIME independent of each other. What would be the MySQL query to get MAX of all dates in 1 query?
t1: DATE_TIME
t2: DATE_TIME
t3: DATE_TIME
t4: DATE_TIME
Desired result
---------------------------------------------------------
| max_t1_date | max_t2_date | max_t3_date | max_t4_date |
---------------------------------------------------------
Many ways to skin this cat...
SELECT max( t1.a ) AS max_table1date,
max( t2.a ) AS max_table2date,
max( t3.a ) AS max_table3date
FROM table1 t1,
table2 t2,
table3 t3
It's been a while since I used MySQL syntax and I cannot try this at the moment, but this should work:
SELECT
(SELECT MAX(date_time) FROM t1) AS max_t1_date,
(SELECT MAX(date_time) FROM t2) AS max_t2_date,
(SELECT MAX(date_time) FROM t3) AS max_t3_date,
(SELECT MAX(date_time) FROM t4) AS max_t4_date
SELECT t1.MaxDate max_t1_date,
t2.MaxDate max_t2_date,
t3.MaxDate max_t3_date,
t4.MaxDate max_t4_date
FROM (SELECT MAX(DATE_TIME) MaxDate FROM t1) t1
(SELECT MAX(DATE_TIME) MaxDate FROM t2) t2,
(SELECT MAX(DATE_TIME) MaxDate FROM t3) t3,
(SELECT MAX(DATE_TIME) MaxDate FROM t4) t4
Related
Hypothetical data -
tbl1 -
id
date
value1
101
2021-01-01
200
101
2021-01-03
400
tbl2 -
id
date
value2
101
2021-01-01
600
101
2021-01-02
900
My expected result is -
id
date
value1
value2
101
2021-01-01
200
600
101
2021-01-02
NaN
900
101
2021-01-03
400
NaN
select * from (select * from tbl1 where id in
(another query)) t1
left join tbl2 as t2 on t1.id = t2.id and t1.date = t2.date
union all
select * from (select * from tbl1 where id in
(another query)) t1
right join tbl2 as t2 on t1.id = t2.id and t1.date = t2.date
where t1.id is null and t1.date is null
I am unable to figure out where am I going wrong.
I think you might be overcomplicating your union query:
SELECT t1.id, t1.date, t1.value1, t2.value2
FROM tbl1 t1
LEFT JOIN tbl2 t2 ON t1.id = t2.id AND t1.date = t2.date
UNION ALL
SELECT t2.id, t2.date, t1.value1, t2.value2
FROM tbl1 t1
RIGHT JOIN tbl2 t2 ON t1.id = t2.id AND t1.date = t2.date
WHERE t1.id IS NULL
ORDER BY id, date;
Demo
Collect all present (id, `date`) pairs then join source data to it:
SELECT id, `date`, tbl1.value1, tbl2.value2
FROM ( SELECT id, `date` FROM tbl1
UNION
SELECT id, `date` FROM tbl2 ) combined
LEFT JOIN tbl1 USING (id, `date`)
LEFT JOIN tbl2 USING (id, `date`);
fiddle
The solution assumes that (id, `date`) is unique over each separate source table. If not then some aggregation must be used (SUM or MAX, depends on the logic).
I have a MySQL table with position key (65,000 records). I deleted, updated some rows in the middle of the table. Now I have, for example, something like this in the position 1 - 6 - 2 - 9
id
category
position
1
1
1
2
1
6
3
2
2
4
2
9
I want to reset / reorder the position key
id
category
position
1
1
1
2
1
2
3
2
1
4
2
2
How can I reset position where category = 1
and where category = 2?
Try this:
UPDATE source_table
JOIN ( SELECT id, ROW_NUMBER() OVER (PARTITION BY category ORDER BY position) position
FROM source_table ) subquery USING (id)
SET source_table.position = subquery.position
mysql> SHOW VARIABLES LIKE "%version%"; 5.7.24 – sagittarius
UPDATE source_table
JOIN ( SELECT t1.id, COUNT(t2.id) position
FROM source_table t1
JOIN source_table t2 ON t1.category = t2.category
AND t1.position >= t2.position
GROUP BY t1.id ) subquery USING (id)
SET source_table.position = subquery.position;
fiddle
if position is duplicated everything crashes – sagittarius
UPDATE source_table
JOIN ( SELECT t1.id, COUNT(t2.id) position
FROM source_table t1
JOIN source_table t2 ON t1.category = t2.category
AND ( t1.position > t2.position
OR ( t1.position = t2.position
AND t1.id >= t2.id ))
GROUP BY t1.id ) subquery USING (id)
SET source_table.position = subquery.position;
fiddle
UPDATE source_table t1
INNER JOIN
(
SELECT id,category,position, ROW_NUMBER() OVER (PARTITION BY category
ORDER BY position) position2
FROM source_table
) t2
ON t2.id = t1.id
SET
t1.position = t2.position2
I think this code is easy to understand and apply.
I have a table table_1
id contact_id
1 500
5 89
8 35
15 458
... ...
555 38
how I can mix contact_id, result for table_1
id contact_id
1 35
5 458
8 35
15 89
... ...
555 45
You can randomly assign the contact ids using variables or row_number() (in MySQL 8+):
select t1.id, tt1.contact_id
from (select t1.*, row_number() over (order by id) as seqnum
from table_1 t1
) t1 join
(select t1.*, row_number() over (order by rand()) as seqnum
from table_1 t1
) tt1
on t1.seqnum = tt1.seqnum;
Without much difficulty (but more typing), this can be transformed to use variables in earlier versions.
You can also incorporate this into an update statement, if you want to shuffle the values permanently.
EDIT:
I think you want:
update table1 t1 join
(select t1.id, tt1.contact_id
from (select t1.*, (#rn1 := #rn1 + 1) as seqnum
from (select * table_1 order by id) t1 cross join
(select #rn1 := 0) params
) t1 join
(select t1.*, (#rn2 := #rn2 + 1) as seqnum
from (select * from table_1 order by rand()) t1 cross join
(select #rn2 := 0) params
) tt1
on t1.seqnum = tt1.seqnum
) tt1
on tt1.id = t1.id
set t1.contact_id = tt1.contact_id;
Can someone help in simplifying below query. Cost of it shows as 58.
b.dueDate and b.tID are composite key.
a.tID is primary key and foreign key between table 1 and 2.
SELECT test.tID, test.sor_acct_id, test.pmt, test.status FROM ct.tab1 a,
(SELECT a.tID, a.sor_acct_id, b.dueDate, b.amt, b.status, a.pmt,
Row_number() OVER ( partition BY a.tID ORDER BY b.dueDate DESC) AS rn
FROM ct.tab1 a
INNER JOIN ct.tab2 b
ON a.tID = b.tID
WHERE a.tID IN (SELECT a.tID
FROM ct.tab1 a
INNER JOIN
ct.tab2 b
ON a.tID =
b.tID
WHERE a.status = 'E'
AND a.pmt IS NOT NULL
AND a.pmt <> '{}'
AND b.dueDate > CURRENT_DATE - 4
AND b.dueDate < CURRENT_DATE)
AND b.dueDate > CURRENT_DATE - 1
) test WHERE rn = 1
AND test.status IN ( 'X', 'Z' )
AND a.tID = test.tID
Maybe you would change:
WHERE a.tID IN (SELECT a.tID ....
into:
join ((SELECT a.tID FROM ct.tab1 a ....) t on t.tID=a.tID
tID is tab1's primary key. So when you say you are looking for tab1 records the tID of which is found in a set of tab1 records with status E, you could just as well simply say: I'm looking for tab1 records with status E.
What your query does is: Show all tab1 records with their final tab2 status provided ...
the tab1 pmt is not null and not '{}'
the tab1 status is E
the final tab2 status is X or Z
the final tab2 status is due today or in the future
there exists at least one tab2 record due in the last three days for the tab1 record
The query:
SELECT
t1.tID,
t1.sor_acct_id,
t1.pmt,
t2.status
FROM ct.tab1 t1
join
(
SELECT
tID,
status,
ROW_NUMBER() OVER (PARTITION BY tID ORDER BY dueDate DESC) AS rn
FROM ct.tab2
WHERE dueDate > CURRENT_DATE - 1
) t2 ON t2.tID = tab1.tID AND t2.rn = 1 AND t2.status IN ('X', 'Z')
WHERE t1.status = 'E'
AND t1.pmt IS NOT NULL
AND t1.pmt <> '{}'
and t1.tID IN
(
SELECT tID
FROM ct.tab2
WHERE dueDate > CURRENT_DATE - 4
AND dueDate < CURRENT_DATE
);
I have table like:
id col1 col2
1 a 55
2 b 77
In result i want to see:
id col1 col2 MIN(col2)
1 a 55 55
2 b 77
Something like that, or in other case, how i can get one minimum value with whole table.
You can use a CROSS JOIN with a subquery which will select the min(col2) value for the entire table:
select t1.id,
t1.col1,
t1.col2,
t2.minCol2
from yourtable t1
cross join
(
select min(col2) minCol2
from yourtable
) t2
See SQL Fiddle with Demo.
If you want to expand this to only show the min(col2) value on the first row, then you could use user-defined variables:
select id,
col1,
col2,
case when rn = 1 then mincol2 else '' end mincol2
from
(
select t1.id,
t1.col1,
t1.col2,
t2.minCol2,
#row:=case when #prev:=t1.id then #row else 0 end +1 rn,
#prev:=t1.id
from yourtable t1
cross join
(
select min(col2) minCol2
from yourtable
) t2
cross join (select #row:=0, #prev:=null) r
order by t1.id
) d
order by id
See SQL Fiddle with Demo
If you had more than one column that you want to compare, then you could unpivot the data using a UNION ALL query and then select the min value for the result:
select t1.id,
t1.col1,
t1.col2,
t2.MinCol
from yourtable t1
cross join
(
select min(col) MinCol
from
(
select col2 col
from yourtable
union all
select col3
from yourtable
) src
) t2
See SQL Fiddle with Demo
You can't. The number of columns is fixed, so you can get the minimum value on all the rows as described by #bluefeet.
You could get it on a smaller number of rows (typically 1) by using the logic:
(case when t2.minCol2 = t1.col2 then t2.minCol2 end)
But this would put NULLs on the other rows.