how to aggregation without group_by in mysql? - mysql

This is table.
idx
statusIdx
date
1
1
2022-05-12 02:24
2
2
2022-05-12 02:24
3
3
2022-06-12 02:24
4
1
2022-07-12 02:24
5
1
2022-07-12 02:24
6
2
2022-07-12 02:24
How can i get like this?
stauts1
status2
status3
2022-05
1
1
0
2022-06
0
0
1
2022-07
2
1
0
sum
3
2
1
I've tried to use row_number() and count() over().
SELECT
FDATE, cnt1, cnt2, cnt3
FROM
(SELECT
DATE_FORMAT(date, "%Y.%m") AS FDATE,
COUNT(case when statusIdx=1 then 1 end) over(PARTITION BY date, statusIdx) AS cnt1,
COUNT(case when statusIdx=2 then 1 end) over(PARTITION BY date, statusIdx) AS cnt2,
COUNT(case when statusIdx=3 then 1 end) over(PARTITION BY date, statusIdx) AS cnt3,
row_number() over (PARTITION by date, statusIdx) AS rnk
FROM transfer
WHERE date betWEEN "20212-05-01" AND "2022-07-31"
ORDER BY FDATE ASC
) t
WHERE rnk = 1
It show vertically counting.
num
FDATE
cnt1
cnt2
cnt3
1
2022-05
1
0
0
1
2022-05
0
1
0
3
2022-06
0
0
1
4
2022-07
2
0
0
5
2022-07
0
1
0
How to aggregation without group_by in mysql?

Used sum() over partition. see dbfidde link if this works.

Related

How do I Rank column in SQL based on row day-difference and partition?

I am trying to get RANK() on a column based on a row difference < 3.
select hotel.*,
IFNULL(datediff(visit_date, lag(visit_date)
OVER (partition by hotel_id)), 0) as diff
from hotel;
I get the following output,
hotel_id customer_id visit_date diff
1 1 2020-01-01 0
1 2 2020-01-03 2
2 1 2020-01-01 0
2 2 2020-01-10 9
2 3 2020-01-14 4
3 1 2020-01-04 0
3 1 2020-01-11 7
I am stuck with the RANK() part.
Expected Output:
If Day Difference is less than 3 then 1 else 2. And if the next one is greater than 3 days the 3, and so on
hotel_id customer_id visit_date rank
1 1 2020-01-01 1
1 2 2020-01-03 1
2 1 2020-01-01 1
2 2 2020-01-10 2
2 3 2020-01-14 3
3 1 2020-01-04 1
3 1 2020-01-11 2
You can use this query to generate your rank values. It uses a couple of CTEs, the first to generate row numbers for each visit (on a per-hotel basis), and the second (recursive) CTE to generate the rank values, iterating through the rows from the first CTE and only incrementing the rank when the difference in dates is more than 2 days:
WITH RECURSIVE hotel_rows AS (
SELECT hotel_id, customer_id, visit_date,
ROW_NUMBER() OVER (PARTITION BY hotel_id ORDER BY visit_date) AS rn
FROM hotel
ORDER BY hotel_id, visit_date
),
ranks AS (
SELECT hotel_id, customer_id, visit_date, rn, 1 AS `rank`
FROM hotel_rows
WHERE rn = 1
UNION ALL
SELECT h.hotel_id, h.customer_id, h.visit_date, h.rn,
r.rank + (h.visit_date > r.visit_date + INTERVAL 2 DAY)
FROM hotel_rows h
JOIN ranks r ON h.hotel_id = r.hotel_id
AND h.rn = r.rn + 1
)
SELECT SELECT hotel_id, customer_id, visit_date, `rank`
FROM ranks
ORDER BY hotel_id, visit_date
Output (for my slightly extended demo):
hotel_id customer_id visit_date rank
1 1 2020-01-01 1
1 2 2020-01-03 1
2 1 2020-01-01 1
2 2 2020-01-10 2
2 3 2020-01-14 3
2 1 2020-01-15 3
2 2 2020-01-20 4
3 1 2020-01-04 1
3 1 2020-01-11 2
Demo on dbfiddle
If you want the result as per your given condition then you can try below in SQL Server. here is the Demo
select
hotel_id,
customer_id,
visit_date,
case
when days < 3 then 1
else 2
end as rnk
from
(
select
*,
datediff(day, n_date, visit_date) as days
from
(
select
*,
coalesce(lag(visit_date) over (partition by hotel_id order by visit_date), visit_date) as n_date
from hotel
) val
)days
I would express this as:
select h.*,
(case when lag(visit_date) over (partition by hotel_id order by visit_date) < visit_date - interval 3 day
then 2 else 1
end)
from hotel h;
Edit;
Based on your revised point, you want to assign groups based on the date difference and then use row_number():
select h.*,
1 + sum( coalesce(visit_date > prev_vd + interval 3 day, 0) ) over (partition by hotel_id order by visit_date) as grp
from (select h.*,
lag(visit_date) over (partition by hotel_id order by visit_date) as prev_vd
from hotel h
) h;
Here is a db<>fiddle.

SQL+Fetch rows with latest date+Case when row_number()+Duplicates

I have a table with fields(id, date, product) with below sample data
id date Product current_Flag Expected_flag
14834 2019-01-03 00:00:00 A 1 1
14834 2019-01-31 00:00:00 B 0 0
14834 2019-02-28 00:00:00 C 0 0
14834 2019-03-30 00:00:00 C 0 0
14834 2019-01-03 00:00:00 D 0 1
I'm trying the case when row_number() over (partition by id order by date) = 1 then 1 else 0 end as flag,
But for a particular distinct Id with min date, it is getting flag as 1, but I need to flag as for a particular Id & min date and product as 1 flag as shown in Expected_flag
case when row_number() over (partition by id order by date) = 1 then 1 else 0 end as flag
You need dense_rank() instead :
case when dense_rank() over (partition by id order by date) = 1 then 1 else 0 end as Expected_flag

How to group by diapasons? [duplicate]

This question already has answers here:
In SQL, how can you "group by" in ranges?
(17 answers)
Closed 4 years ago.
I have got a table 'payments'
user_id amount
1 300
1 100
2 100
2 100
3 10
4 200
What query should I make to display result by groups:
diapason number
0 -10 0
10 - 100 1
100 -200 3
more than 200 2
I think I should use 'having'?
For this type of query you could use a UNION:
SELECT '0-10' as diapason, SUM(CASE WHEN amount < 10 THEN 1 ELSE 0 END) AS number FROM payments
UNION
SELECT '10-100', SUM(CASE WHEN amount BETWEEN 10 AND 99 THEN 1 ELSE 0 END) FROM payments
UNION
SELECT '100-200', SUM(CASE WHEN amount BETWEEN 100 AND 199 THEN 1 ELSE 0 END) FROM payments
UNION
SELECT 'more than 200', SUM(CASE WHEN amount >= 200 THEN 1 ELSE 0 END) FROM payments
Output:
diapason number
0-10 0
10-100 1
100-200 3
more than 200 2
SQLFiddle Demo

MySql: Count occurrences of values by date

I'm trying to count the number of occurences based severity level (1-5) on distinct dates. Note I have another table but severity levels are words (High, Medium and Low...not 1 to 5).
Example of DB:
DATE LEVEL COUNT
---- ----- -----
05/11/2018 3 14
05/11/2018 5 11
05/11/2018 5 11
05/12/2018 3 14
05/12/2018 2 14
05/13/2018 2 11
05/13/2018 1 12
Expected output
Date 1 2 3 4 5
--------- -- -- -- -- --
05/11/2018 0 0 14 0 22
05/12/2018 0 14 14 0 0
05/13/2018 12 11 0 0 0
Expected output 2
Level 05/11/2018 05/12/2018 05/13/2018
--------- ---------- ---------- ----------
1 0 0 12
2 0 14 11
3 14 14 0
4 0 0 0
5 22 0 0
I tried
SELECT CONCAT(DAY(`DATE`) ,MONTH(`DATE`) , YEAR(`DATE`)) AS DDMMYYYY ,
COUNT(DISTINCT LEVEL) as NumCount
FROM `myDatabase`
GROUP BY CONCAT(DAY(`DATE`),MONTH(`DATE`), YEAR(`DATE`) )
but I'm getting the number of different counts..
Any guidance would be appreciated! Thx!
You can't really do pivot tables in MySQL. However with a fixed number of columns (such as expected output #1) you can simulate them with CASE statements e.g.
select date_format(date, '%d%m%Y') as Date,
sum(case when level=1 then count else 0 end) as `1`,
sum(case when level=2 then count else 0 end) as `2`,
sum(case when level=3 then count else 0 end) as `3`,
sum(case when level=4 then count else 0 end) as `4`,
sum(case when level=5 then count else 0 end) as `5`
from table1
group by Date
Output:
Date 1 2 3 4 5
11052018 0 0 14 0 22
12052018 0 14 14 0 0
13052018 12 11 0 0 0

mysql - return row where date is equal to some value

I have table assessment as given below-
SLNO EID Period_From Period_To
1 101 2017-06-01 2017-11-14
2 102 2017-07-01 2017-09-30
3 103 2017-05-01 2017-07-31
If Period_To and currentdate is equal to 75 days then row should return 1 else 0 I used below query-
SELECT SLNO,EID, Period_From,Period_To,(CASE WHEN (PERIOD_TO = (select DATE_ADD(PERIOD_TO,INTERVAL 75 DAY))) THEN 1 ELSE 0 END) AS ASSESSMENT_ENABLE from assessment;
I got result as
SLNO EID Period_From Period_To ASSESSMENT_ENABLE
1 101 2017-06-01 2017-11-14 0
2 102 2017-07-01 2017-09-30 0
3 103 2017-05-01 2017-07-31 0
I am getting wrong result. Please help me.
i don't think you need sub query. try this it works for me
SELECT SLNO,EID, Period_From,Period_To,
(CASE WHEN (PERIOD_TO = DATE_FORMAT(CURDATE(), '%Y-%m-%d') - INTERVAL 75 DAY) THEN 1 ELSE 0 END)
AS ASSESSMENT_ENABLE
Short solution using CURRENT_DATE and DATEDIFF functions:
SELECT
SLNO, EID, Period_From, Period_To,
IF(DATEDIFF(CURRENT_DATE(), date_to) = 75, 1, 0) AS ASSESSMENT_ENABLE
FROM
ASSESSMENT
https://dev.mysql.com/doc/refman/5.7/en/date-and-time-functions.html
You can try this-
select
SLNO,
EID,
Period_From,
Period_To,
case when (DATEDIFF(now(),PERIOD_TO)=75) then 1 else 0 end as ASSESSMENT_ENABLE
from
assessment;