How to do complex order by in SQL Server - sql

I am trying to do a complex order by or possibly a group by and then order by. The table name is curtomer_updates. What I want it to do is first of all sort by descending order on the last_updated_date and then have a unique cust_id together sorted by last_updated_date. Below is an example of what it is right now and the expected result. Thank you for any help.
Table normally sorted
Update_ID
Cust_Id
Field_updated
Last_updated_date
Updated_by
1
1223
Name
2021-11-01 12:23
Frodo Baggins
2
9999
address
2021-12-02 19:23
Legolas
3
2200
phone
2021-12-03 23:00
Bilbo Baggins
4
2200
Name
2022-01-04 02:23
Bilbo Baggins
5
9999
phone
2022-02-05 12:23
Golum
6
9999
address
2022-03-06 20:00
Sauron
7
1223
address
2022-04-07 01:24
Gandalf
8
2200
email
2022-05-08 12:50
Some Urkai
9
3412
email, phone
2022-06-08 08:45
Golum
10
1223
address
2022-07-10 00:23
Pippin
11
3412
email, address
2022-09-22 16:48
Gandalf
Expected result
Update_ID
Cust_Id
Field_updated
Last_updated_date
Updated_by
11
3412
email, address
2022-09-22 16:48
Gandalf
9
3412
email, phone
2022-06-08 08:45
Golum
10
1223
address
2022-07-10 00:23
Pippin
7
1223
address
2022-04-07 01:24
Gandalf
1
1223
Name
2021-11-01 12:23
Frodo Baggins
8
2200
email
2022-05-08 12:50
Some Urkai
4
2200
Name
2022-01-04 02:23
Bilbo Baggins
3
2200
phone
2021-12-03 23:00
Bilbo Baggins
6
9999
address
2022-03-06 20:00
Sauron
5
9999
phone
2022-02-05 12:23
Golum
2
9999
address
2021-12-02 19:23
Legolas

SELECT *
FROM curtomer_updates
ORDER BY
MAX(Last_updated_date) OVER (PARTITION BY cust_id) DESC
,Last_updated_date DESC
using sample set:
SELECT *
FROM ( VALUES
(1,1223, 'Name', '2021-11-01 12:23', 'Frodo Baggins'),
(2,9999, 'address', '2021-12-02 19:23', 'Legolas'),
(3,2200, 'phone', '2021-12-03 23:00', 'Bilbo Baggins'),
(4,2200, 'Name', '2022-01-04 02:23', 'Bilbo Baggins'),
(5,9999, 'phone', '2022-02-05 12:23', 'Golum'),
(6,9999, 'address', '2022-03-06 20:00', 'Sauron'),
(7,1223, 'address', '2022-04-07 01:24', 'Gandalf'),
(8,2200, 'email', '2022-05-08 12:50', 'Some Urkai'),
(9,3412, 'email, phone', '2022-06-08 08:45', 'Golum'),
(10,1223, 'address', '2022-07-10 00:23', 'Pippin'),
(11,3412, 'email, address', '2022-09-22 16:48', 'Gandalf')
)sub(Update_ID, Cust_Id , Field_updated , Last_updated_date, Updated_by)
ORDER BY
MAX(Last_updated_date) OVER (PARTITION BY cust_id) DESC
,Last_updated_date DESC
Returns:
Update_ID Cust_Id Field_updated Last_updated_date Updated_by
----------------------------------------------------------------------------------
11 3412 email, address 2022-09-22 16:48 Gandalf
9 3412 email, phone 2022-06-08 08:45 Golum
10 1223 address 2022-07-10 00:23 Pippin
7 1223 address 2022-04-07 01:24 Gandalf
1 1223 Name 2021-11-01 12:23 Frodo Baggins
8 2200 email 2022-05-08 12:50 Some Urkai
4 2200 Name 2022-01-04 02:23 Bilbo Baggins
3 2200 phone 2021-12-03 23:00 Bilbo Baggins
6 9999 address 2022-03-06 20:00 Sauron
5 9999 phone 2022-02-05 12:23 Golum
2 9999 address 2021-12-02 19:23 Legolas

You can do:
select t.*
from customer_updates t
join (
select cust_id, dense_rank() over(order by max(last_updated_date)) as rk
from customer_updates
group by cust_id
) x on x.cust_id = t.cust_id
order by x.rk desc, t.last_updated_date desc
Result:
update_id Cust_Id Field_updated Last_updated_date Updated_by
---------- -------- --------------- ------------------ -------------
11 3412 email, address 2022-09-22 16:48 Gandalf
9 3412 email, phone 2022-06-08 08:45 Golum
10 1223 address 2022-07-10 00:23 Pippin
7 1223 address 2022-04-07 01:24 Gandalf
1 1223 Name 2021-11-01 12:23 Frodo Baggins
8 2200 email 2022-05-08 12:50 Some Urkai
4 2200 Name 2022-01-04 02:23 Bilbo Baggins
3 2200 phone 2021-12-03 23:00 Bilbo Baggins
6 9999 address 2022-03-06 20:00 Sauron
5 9999 phone 2022-02-05 12:23 Golum
2 9999 address 2021-12-02 19:23 Legolas
See running example at db<>fiddle.

Related

How to count the number of campaigns per day based on the start and end dates of the campaigns in SQL

I need to count the number of campaigns per day based on the start and end dates of the campaigns
Input Table:
Campaign name
Start date
End date
Campaign A
2022-07-10
2022-09-25
Campaign B
2022-08-06
2022-10-07
Campaign C
2022-07-30
2022-09-10
Campaign D
2022-08-26
2022-10-24
Campaign E
2022-07-17
2022-09-29
Campaign F
2022-08-24
2022-09-12
Campaign G
2022-08-11
2022-10-24
Campaign H
2022-08-26
2022-11-22
Campaign I
2022-08-29
2022-09-25
Campaign J
2022-08-21
2022-11-15
Campaign K
2022-07-20
2022-09-18
Campaign L
2022-07-31
2022-11-20
Campaign M
2022-08-17
2022-10-10
Campaign N
2022-07-27
2022-09-07
Campaign O
2022-07-29
2022-09-26
Campaign P
2022-07-06
2022-09-15
Campaign Q
2022-07-16
2022-09-22
Out needed (result):
Date
Count unique campaigns
2022-07-02
17
2022-07-03
47
2022-07-04
5
2022-07-05
5
2022-07-06
25
2022-07-07
27
2022-07-08
17
2022-07-09
58
2022-07-10
23
2022-07-11
53
2022-07-12
18
2022-07-13
29
2022-07-14
52
2022-07-15
7
2022-07-16
17
2022-07-17
37
2022-07-18
33
How do I need to write the SQL command to get the above result? thanks all
In the following solutions we leverage string_split with combination with replicate to generate new records.
select dt as date
,count(*) as Count_unique_campaigns
from
(
select *
,dateadd(day, row_number() over(partition by Campaign_name order by (select null))-1, Start_date) as dt
from (
select *
from t
outer apply string_split(replicate(',',datediff(day, Start_date, End_date)),',')
) t
) t
group by dt
order by dt
date
Count_unique_campaigns
2022-07-06
1
2022-07-07
1
2022-07-08
1
2022-07-09
1
2022-07-10
2
2022-07-11
2
2022-07-12
2
2022-07-13
2
2022-07-14
2
2022-07-15
2
2022-07-16
3
2022-07-17
4
2022-07-18
4
2022-07-19
4
2022-07-20
5
2022-07-21
5
2022-07-22
5
2022-07-23
5
2022-07-24
5
2022-07-25
5
2022-07-26
5
2022-07-27
6
2022-07-28
6
2022-07-29
7
2022-07-30
8
2022-07-31
9
2022-08-01
9
2022-08-02
9
2022-08-03
9
2022-08-04
9
2022-08-05
9
2022-08-06
10
2022-08-07
10
2022-08-08
10
2022-08-09
10
2022-08-10
10
2022-08-11
11
2022-08-12
11
2022-08-13
11
2022-08-14
11
2022-08-15
11
2022-08-16
11
2022-08-17
12
2022-08-18
12
2022-08-19
12
2022-08-20
12
2022-08-21
13
2022-08-22
13
2022-08-23
13
2022-08-24
14
2022-08-25
14
2022-08-26
16
2022-08-27
16
2022-08-28
16
2022-08-29
17
2022-08-30
17
2022-08-31
17
2022-09-01
17
2022-09-02
17
2022-09-03
17
2022-09-04
17
2022-09-05
17
2022-09-06
17
2022-09-07
17
2022-09-08
16
2022-09-09
16
2022-09-10
16
2022-09-11
15
2022-09-12
15
2022-09-13
14
2022-09-14
14
2022-09-15
14
2022-09-16
13
2022-09-17
13
2022-09-18
13
2022-09-19
12
2022-09-20
12
2022-09-21
12
2022-09-22
12
2022-09-23
11
2022-09-24
11
2022-09-25
11
2022-09-26
9
2022-09-27
8
2022-09-28
8
2022-09-29
8
2022-09-30
7
2022-10-01
7
2022-10-02
7
2022-10-03
7
2022-10-04
7
2022-10-05
7
2022-10-06
7
2022-10-07
7
2022-10-08
6
2022-10-09
6
2022-10-10
6
2022-10-11
5
2022-10-12
5
2022-10-13
5
2022-10-14
5
2022-10-15
5
2022-10-16
5
2022-10-17
5
2022-10-18
5
2022-10-19
5
2022-10-20
5
2022-10-21
5
2022-10-22
5
2022-10-23
5
2022-10-24
5
2022-10-25
3
2022-10-26
3
2022-10-27
3
2022-10-28
3
2022-10-29
3
2022-10-30
3
2022-10-31
3
2022-11-01
3
2022-11-02
3
2022-11-03
3
2022-11-04
3
2022-11-05
3
2022-11-06
3
2022-11-07
3
2022-11-08
3
2022-11-09
3
2022-11-10
3
2022-11-11
3
2022-11-12
3
2022-11-13
3
2022-11-14
3
2022-11-15
3
2022-11-16
2
2022-11-17
2
2022-11-18
2
2022-11-19
2
2022-11-20
2
2022-11-21
1
2022-11-22
1
For SQL in Azure and SQL Server 2022 we have a cleaner solution based on [ordinal][4].
"The enable_ordinal argument and ordinal output column are currently
supported in Azure SQL Database, Azure SQL Managed Instance, and Azure
Synapse Analytics (serverless SQL pool only). Beginning with SQL
Server 2022 (16.x) Preview, the argument and output column are
available in SQL Server."
select dt as date
,count(*) as Count_unique_campaigns
from
(
select *
,dateadd(day, ordinal-1, Start_date) as dt
from (
select *
from t
outer apply string_split(replicate(',',datediff(day, Start_date, End_date)),',', 1)
) t
) t
group by dt
order by dt
Fiddle
Your sample data doesn't seem to match your desired results, but I think what you're after is this:
DECLARE #Start date, #End date;
-- first, find the earliest and last date:
SELECT #Start = MIN([Start date]), #End = MAX([End date])
FROM dbo.Campaigns;
-- now use a recursive CTE to build a date range,
-- and count the number of campaigns that have a row
-- where the campaign was active on that date:
WITH d(d) AS
(
SELECT #Start
UNION ALL
SELECT DATEADD(DAY, 1, d) FROM d WHERE d < #End
)
SELECT
[Date] = d,
[Count unique campaigns] = COUNT(*)
FROM d
INNER JOIN dbo.Campaigns AS c
ON d.d >= c.[Start date] AND d.d <= c.[End date]
GROUP BY d.d OPTION (MAXRECURSION 32767);
Working example in this fiddle.

check if the person have pervious record with certain date :db2 sql

i have the following table :
id name start end
1 Asla 2021-01-01 2021-12-31
1 Asla 2022-01-01 2022-04-15
2 Tina 2021-05-16 2021-09-23
3 Layla 2021-01-01 2021-09-27
3 Layla 2022-01-01 2022-07-18
2 Sim 2020-05-12 2020-08-13
3 Anderas 2021-07-01 2021-09-13
3 Anderas 2021-10-01 2021-11-18
3 Anderas 2022-01-01 2029-11-18
4 Klara 2022-01-01 null
what i want to do get persons that have work (date) under 2021 and create a new column that show status (if the person continue having work under 2022 -- ok else not ok and if the person is new like 'Klara' get new ) and show last record for every person . maybe too End = null ??????
i tried this .
select w.id ,w.name ,w.start ,w.end, max_date.end
from Work_date w
left join (select * from Work_date where start>='2022-01-01')max_date on max_date.id=id
where w.start>='2021-01-01'
``` but the problem i get the result as this
<pre>
id name start end
1 Asla 2021-01-01 null
1 Asla 2022-01-01 2022-04-15
2 Tina 2021-05-16 null
3 Layla 2021-01-01 null
3 Layla 2022-01-01 2022-07-18
3 Anderas 2021-07-01 null
3 Anderas 2021-10-01 2021-11-18
3 Anderas 2022-01-01 null
4 Klara 2022-01-01 null
</pre>
men i want to get result as <pre>
id name start end status
1 Asla 2022-01-01 2022-04-15 ok
2 Tina 2021-05-16 2021-09-23 not ok
3 Layla 2022-01-01 2022-07-18 ok
3 Anderas 2022-01-01 2029-11-18 ok
4 Klara 2022-01-01 null ok
Looks like you can simply aggregate.
Then use a CASE WHEN for the status.
select
w.id
, w.name
, max(w.start) as start
, max(w.end) as end
, case
when year(max(end)) < 2022 then 'not ok'
else 'ok'
end as status
from Work_date w
where w.start >= '2021-01-01'
group by w.id, w.name
order by w.id, max(w.start), max(w.end);
ID
NAME
START
END
STATUS
1
Asla
2022-01-01
2022-04-15
ok
2
Tina
2021-05-16
2021-09-23
not ok
3
Layla
2022-01-01
2022-07-18
ok
3
Anderas
2022-01-01
2029-11-18
ok
4
Klara
2022-01-01
null
ok
Demo on db<>fiddle here

Attendance Log using MS Access or SQL Server

I'm working this almost a month but I think I need some help now. I have a time logs below. I'm using MS Access and C#. Please help what select query
ID BADGE CHECKTIME
-----------------------------
1 1507010 5/31/2018 8:51
1 1507010 5/31/2018 19:52
2 1708004 5/31/2018 6:35
2 1708004 5/31/2018 13:43
3 1708005 5/31/2018 19:23
3 1708005 6/1/2018 8:34
4 1708006 5/31/2018 7:51
4 1708006 6/1/2018 18:34
5 1708007 5/31/2018 19:23
5 1708007 6/1/2018 6:36
6 1708009 5/31/2018 7:11
6 1708009 5/31/2018 7:12
6 1708009 5/31/2018 22:02
6 1708009 5/31/2018 22:03
I want to become this.please help. what the best query to get this data.
ID Badge IN OUT
--------------------------------------------
1 1507010 5/31/2018 8:51 5/31/2018 13:43
2 1708004 5/31/2018 6:35 5/31/2018 13:43
3 1708005 5/31/2018 19:23 6/1/2018 8:34
4 1708006 5/31/2018 7:51 6/1/2018 18:34
5 1708007 5/31/2018 19:23 6/1/2018 6:36
6 1708009 5/31/2018 7:12 5/31/2018 22:03
The following query should get close to what you want:
SELECT
ID,
Badge,
MIN(CHECKTIME) AS [IN],
MAX(CHECKTIME) AS [OUT]
FROM yourTable
GROUP BY
ID,
Badge;
I have a doubt about your expected output for badge 1708009, since the earliest check time for that badge is 7:11, not 7:12.
I would use row_number() inside the subquery :
select id, badge, min(checktime) as in, max(checktime) as out
from (select *, row_number() over (partition by id, badge, cast(checktime as date), datepart(hh,checktime)
order by datepart(mm,checktime) desc) seq
from table
) t
where seq = 1
group by id, badge;

How to group field by id and find the sum?

I have the following data
id starting_point ending_point Date
A 2525 6565 25/05/2017 13:25:00
B 5656 8989 25/01/2017 10:55:00
A 1234 5656 20/05/2017 03:20:00
A 4562 6245 01/02/2017 19:45:00
B 6496 9999 06/12/2016 21:55:00
B 1122 2211 20/03/2017 18:30:00
How to group the data by their id in the ascending order of date and find the sum of first stating point and last starting point. In this case,
Expected output is :
id starting_point ending_point Date Value
A 4562 6245 01/02/2017 19:45:00
A 1234 5656 20/05/2017 03:20:00
A 2525 6565 25/05/2017 13:25:00 4532 + 6565 = 11127
B 6496 9999 06/12/2016 21:55:00
B 1122 2211 20/03/2017 18:30:00 6496 + 2211 = 8707
IIUC:
In [146]: x.groupby('id').apply(lambda df: df['starting_point'].head(1).values[0]
+ df['ending_point'].tail(1).values[0])
Out[146]:
id
A 8770
B 7867
dtype: int64

How do you summarize row data in sybase table

I have this table in sybase:
Date File_name File_Size customer Id
1/1/205 11:00:00 temp.csv 100000 ESPN 1111
1/1/205 11:10:00 temp.csv 200000 ESPN 1122
1/1/205 11:20:00 temp.csv 400000 ESPN 1456
1/1/205 11:30:00 temp.csv 400000 ESPN 2345
1/2/205 11:00:00 llc.csv 100000 LLC 445
1/2/205 11:10:00 llc1.txt 200000 LLC 677
1/2/205 11:20:00 dtt.txt 500000 LLC 76
1/2/205 11:30:00 jpp.txt 400000 LLC 666
I need to come up with a query to summarize this data by day which will be month/day/Year.
Date total_file_size number_of_unique_customers number_unique_id
1/1/2015 110,000 1 4
1/2/2015 120,000 1 4
How would I do this in sql query? I tried this:
select convert(varchar,arrived_at,110) as Date
sum(File_Size),
count(distinct(customer)),
count(distinct(id))
group by Date
Does not seem to be working, any ideas?
try
select
convert(varchar,arrived_at,110) as Date,
SUM(File_Size),
count(distinct customer) as number_of_unique_customers,
count(distinct id ) as number_unique_id
group by convert(varchar,arrived_at,110)