Order by date a select query on UNION ALL - mysql

I have little problem with my MySql query:
I have two tables:
Table timeline
id | date | text
1 2013-10-13 Hello
Table reps
id | date | text
1 2013-10-12 Its me again
1 2013-10-11 What?
1 2013-10-10 Lorem ipsum
What i am doing is UNION ALL timeline and reps.First row should always be the row from timeline(it's always one row) and then all rows from reps table but in DESC order.
My query is the following one(which work ok except from order by)
select id,date,text from timeline UNION ALL select * from reps order by date desc
Think something like a comment (sits on top) with replies on the comment in desc order,newest first.
Thank you in advance.

Put the UNION in a subquery:
SELECT id, date, text
FROM (SELECT id, date, text, 1 AS priority
FROM timeline
UNION ALL
SELECT *, 2 AS priority
FROM reps) u
ORDER BY priority, date DESC

your query is right , you just close second query by () like that: and it will order just the second query . without () it will order the two queries.
select id,date,text from timeline
UNION all
(select * from reps order by date desc)

Make a Unix_timestamp from the date value and order by its value.
SELECT -1 as 'id' , 99999999999999 as 'sortalias' , now() as 'datum||date'
UNION
( SELECT
id
,unix_timestamp(datum) as 'sortalias'
,datum as 'datum||date'
FROM kunde
)
order by sortalias desc

select id,date,text from (
select id,1 poid,date,text
from timeline
union all
select id,2 poid,date,text
from reps
) t
order by t.id asc,t.poid asc,t.date desc

Related

Show all patients grouped into weight groups. Show the total amount of patients in each weight group. Order the list by the weight group decending

Show all of the patients grouped into weight groups.
Show the total amount of patients in each weight group.
Order the list by the weight group descending.
For example, if they weight 100 to 109 they are placed in the 100 weight group, 110-119 = 110 weight group, etc.
So something like this?
SELECT FLOOR(t.weight/10) * 10 as weightGroup, count(*) as cnt
FROM YourTable t
GROUP BY FLOOR(t.weight/10)
ORDER BY FLOOR(t.weight/10) DESC
I tend to try and avoid expensive floating point functions like FLOOR() or CEIL().
A trick to FLOOR() a number to the next lower integer is to add 0.5 to it and hard-cast it to a signed integer using CONVERT().
WITH
--- some sample data, don't use in final query ...
indata(id,lb) AS (
SELECT 1,101
UNION ALL SELECT 2,102
UNION ALL SELECT 3,103
UNION ALL SELECT 4,104
UNION ALL SELECT 5,105
UNION ALL SELECT 6,106
UNION ALL SELECT 7,107
UNION ALL SELECT 8,108
UNION ALL SELECT 9,109
UNION ALL SELECT 10,110
UNION ALL SELECT 11,111
UNION ALL SELECT 12,112
UNION ALL SELECT 13,113
UNION ALL SELECT 14,114
UNION ALL SELECT 15,115
UNION ALL SELECT 16,116
UNION ALL SELECT 17,117
UNION ALL SELECT 18,118
UNION ALL SELECT 19,119
UNION ALL SELECT 20,120
)
-- real query starts here ...
SELECT
CONVERT ((lb / 10 - 0.5), SIGNED) AS grp
, COUNT(*) AS pat_count
FROM indata
GROUP BY grp
ORDER BY grp DESC;
-- out grp | patcount
-- out -----+----------
-- out 12 | 1
-- out 11 | 10
-- out 10 | 9
This may help
select count (patient_id) as patient_in_group, floor (weight/10)*10 as weight_group
from patients
group by weight_group
order by weight_group desc;
SELECT
count(patient_id),
weight - weight % 10 AS weight_group
FROM patients
GROUP BY weight_group
ORDER BY weight_group DESC
SELECT
COUNT(*) AS patients_in_group,
FLOOR(weight / 10) * 10 AS weight_group
FROM patients
GROUP BY weight_group
ORDER BY weight_group DESC;
SELECT TRUNCATE(weight, -1) AS weight_group,
COUNT(*)
FROM patients
GROUP BY weight_group
ORDER BY weight_group DESC;

Get last distinct value from 2 columns

I would like some help with this code. I'm trying to select the last chat message im MySQL. This is my table:
id
id_user_to
id_user_from
message
timestamp
1
1
2
Hi
1633345082
2
2
1
Hello
1633345083
3
1
3
Another
1633345088
4
3
1
Another2
1633345088
If I were to select the last message of user 1 I would get the second line, as it has the most recent timestamp. How can I do? I tried this code but I don't know how to adapt it to my context as I have to check that the user is taken once either in the from_user_id or to_user_id column, always with the most recent timestamp.
SELECT *
FROM [tableName]
WHERE id IN (
SELECT MAX(id)
FROM [tableName]
GROUP BY code
)
If you want the last message sent or received by a specific user :
select * from [tableName]
where id_user_to = 1 or id_user_from = 1
order by timestamp desc limit 1
ok for your second question:
select * from (
select *, row_number() over (partition by user1,user2 order by timestamp desc) rn
from (
select id ,id_user_to user1,id_user_from user2,message,timestamp
from table where id_user_to =1
union all
select id ,id_user_from, id_user_to,message,timestamp
from table where id_user_from =1
) t ) t where rn = 1
and If you remove conditions on userids inside sub queries , you get the latest messages for all the user ids

GROUP BY and ORDER BY in UNION

I have this query:
SELECT category, description, price, date_added, datetime_created
FROM vc_expense
WHERE trip_id=? AND description LIKE ?
GROUP BY description, price
UNION SELECT category, description, NULL, NULL, NULL
FROM vc_expense_default
WHERE description LIKE ?
ORDER BY CASE
WHEN description LIKE ? AND price THEN 1
WHEN price THEN 2
ELSE 3
END, date_added DESC, datetime_created DESC
LIMIT 5
My problem is that when I GROUP the description+price on row #4, it doesn't take into account that I want the most recent results:
date_added DESC, datetime_created DESC
Is there a way to use ORDER BY after row #4 so I can get the newest items only, it doesn't seem to work because of the UNION
Thanks!
Edit:
The UNION was irrelevant, I just had put it inside parantheses, and get the latest items only from each group, like this:
SELECT e1.category, e1.description, e1.price, e1.date_added, e1.datetime_created
FROM vc_expense e1
LEFT JOIN vc_expense e2 ON (
e1.description=e2.description AND
e1.price=e2.price AND
e1.date_added < e2.date_added
)
WHERE e2.id IS NULL AND e1.trip_id = ? AND e1.description LIKE ?
From the docs:
https://dev.mysql.com/doc/refman/5.7/en/union.html
Use of ORDER BY for individual SELECT statements implies nothing about
the order in which the rows appear in the final result because UNION
by default produces an unordered set of rows
and here's what you need:
To apply ORDER BY or LIMIT to an individual SELECT, place the clause
inside the parentheses that enclose the SELECT:
(SELECT a FROM t1 WHERE a=10 AND B=1 ORDER BY a LIMIT 10) UNION (SELECT a FROM t2 WHERE a=11 AND B=2 ORDER BY a LIMIT 10);

MYSQL: Query 2 tables with union is very slow, how to improve?

I want to query 2 tables with (almost) identical rows at the same time. As a result, I want to get the 5 recent entries (ordered by date, in total), no matter from which table they are from
So far, I tried this:
SELECT date, name, text FROM `table_A`
UNION
SELECT date, name, text FROM `table_B` ORDER BY date desc LIMIT 5
Unfortunately, this query takes about 20 seconds (both tables have ~300.000 rows).
When I just do:
SELECT date, name, text FROM `table_A` ORDER BY date desc LIMIT 5
or
SELECT date, name, text FROM `table_B` ORDER BY date desc LIMIT 5
the query takes only a few milliseconds.
So my question is: How can I improve my query to be faster or what select query should I use to get the 5 latest rows from both tables?
Select the most recent 5 rows in each table before combining them.
SELECT *
FROM (
(SELECT date, name, text FROM table_A ORDER BY date DESC LIMIT 5)
UNION
(SELECT date, name, text FROM table_B ORDER BY date DESC LIMIT 5)
) x
ORDER BY date DESC
LIMIT 5
The problem with your query is that it's first merging the entire tables and removing duplicates before doing the ordering and limiting. The merged table doesn't have an index, so that part is slow.

Retrieve the second latest record with same id

From the following four records, I want to select the OwnerId of second-latest record
ItemId OwnerId Date
11477 20981 2013-05-13
11477 1 2013-05-21
11477 21086 2013-05-22 #this is the one I'm talking about
11477 3868 2013-05-24
How to go about it?
This needs ItemID to be specified,
SELECT *
FROM TableName
WHERE ItemID = '11477'
ORDER BY DATE DESC
LIMIT 1,1
SQLFiddle Demo
However, if you don't want to specify the ItemID, and you want to get all second latest record for every ItemID, you can use a correlated subquery to generate a sequence number for every ItemID based on lastest DATE,
SELECT ItemId, OwnerID, Date
FROM
(
SELECT A.ItemId,
A.OwnerId,
A.Date,
(
SELECT COUNT(*)
FROM tableName c
WHERE c.ItemId = a.ItemId AND
c.Date >= a.Date) AS RowNumber
FROM TableName a
) x
WHERE RowNumber = 2
SQLFiddle Demo
select ownerid
from your_table
order by date desc
limit 1, 1
I think you can just to ORDER BY date descending, which will give you an order from newer to older, then LIMIT 1,1 to get only the second result, which should be the one you look for
SELECT *
FROM table
ORDER BY date DESC
LIMIT 1,1