Grouping on Date difference not getting desired output in SQL - sql

Data In Table
CaseNo
DESTCODE
HotelName
CheckInDate
CheckOutDate
UD-11323
Gangtok
Mayfair Spa Resort & Casino
2022-04-26
2022-04-27
UD-11323
Gangtok
Mayfair Spa Resort & Casino
2022-04-27
2022-04-28
UD-11323
Lachung
Etho Metho
2022-04-28
2022-04-29
UD-11323
Gangtok
Mayfair Spa Resort & Casino
2022-04-29
2022-04-30
Required Output
CaseNo
DESTCODE
HotelName
CheckInDate
CheckOutDate
UD-11323
Gangtok
Mayfair Spa Resort & Casino
2022-04-26
2022-04-28
UD-11323
Lachung
Etho Metho
2022-04-28
2022-04-29
UD-11323
Gangtok
Mayfair Spa Resort & Casino
2022-04-29
2022-04-30
While querying the above data, I used:
min(CheckInDate), max(CheckOutDate) using Group by CaseNo,
DESTCODE,HotelName
The desired output Pick single record for the HotelName "Mayfair Spa Resort & Casino" and DestCode "Gangtok"
The required output is required as mention, in second table.

Your SELECT statement looks incomplete.
In any case, when you're carrying out an aggregation task, you need to define:
which fields are aggregated: "CheckInDate", "CheckOutDate"
which fields are selected: "CaseNo", "DESTCODE", "HotelName"
Then you need to put each non-aggregated field (selected ones) inside the GROUP BY clause, to avoid either DBMS exceptions or more subtle errors in your data.
SELECT CaseNo, DESTCODE, HotelName,
MIN(CheckInDate) AS CheckInDate,
MAX(CheckOutDate) AS CheckOutDate
FROM tab
GROUP BY CaseNo, DESTCODE, HotelName
This is likely to work on all the most common DBMS products.

Related

history of changes to a column

Please, consider the following scenario.
There are 2 tables: Core and History. Core looks as follows
HWDateStart
HWDateEnd
HWQueueID
2022-05-29 10:00:00
2022-06-04 00:45:00
WIN-S671INNTGRE.P00-K0-01
2022-05-29 10:00:00
2022-06-04 00:45:00
WIN-S671INNTGRE.P00-K0-02
History looks as follows
cntDatetime
cntSerialNumber
cntQueueName
cntQueueID
2022-05-29 02:28:00
SN01-01
p00-0000-01
WIN-S671INNTGRE.P00-K0-01
2022-05-29 02:28:00
SN02-01
p00-0000-02
WIN-S671INNTGRE.P00-K0-02
2022-06-04 00:26:00
SN02-02
p00-0000-02
WIN-S671INNTGRE.P00-K0-02
2022-06-04 00:26:00
SN01-01
p00-0000-01
WIN-S671INNTGRE.P00-K0-01
History holds a list of cntSerialNumber changes through the time
The following script that gives the user SerialNumber as it was at the beginning and the end of a certain period
SELECT Convert(date,[HWDateStart])
,Convert(date,[HWDateEnd])
,[HWQueueID]
, HS.cntSerialNumber
, HE.cntSerialNumber
FROM [watchdocstats].[dbo].[tblJT] SNTarget,
[watchdocstats].[dbo].[tblQueueByConfig] HS,
[watchdocstats].[dbo].[tblQueueByConfig] HE
WHERE
SNTarget.HWQueueID = HS.cntQueueID
AND SNTarget.HWQueueID = HE.cntQueueID
AND Convert(date,SNTarget.HWDateStart) = Convert(date,HS.cntDatetime)
AND Convert(date,SNTarget.HWDateEnd) = Convert(date,HE.cntDatetime)
But what if SerialNumber has been changed more than once down the road
Is there a way to select a table that would show commaseparated SerialNumbers in cntSerialNumber column?
Smth, like
(Start)
(End)
HWQueueID
cntSNHist
2022-05-29
2022-06-04
WIN-S671INNTGRE.P00-K0-01
SN01-01
2022-05-29
2022-06-04
WIN-S671INNTGRE.P00-K0-02
SN02-01,SN02-02,SN02-03
Depending on your DBMS, you should be able to use the LISTAGG function along with a GROUP BY clause

filter the data from records in sql

I am having a one table. in which, there are 12 records available. in those i want to filter and get data like from hp cell value source column to before hp cell value source column records.
Here is the table :
seq_id file_name source date
b21345350 a.txt ad 2022-04-15
b32145660 e.txt qe 2022-04-15
c43526890 ace.txt hp 2022-04-15
re2345566 wer.csv hp 2022-04-15
b43251044 op.xlsx fa 2022-04-15
b6512400 ip.csv jm 2022-04-15
b9123420 tb.xlsx tp 2022-04-15
b3214563 cv.txt ux 2022-04-14
b45678900 em.txt hp 2022-04-14
b65357023 rt.csv hp 2022-04-14
b90879081 ty.txt mp 2022-04-14
b19019019 sd.txt jp 2022-04-14
Here it should be output result :
seq_id file_name source date
c43526890 ace.txt hp 2022-04-15
re2345566 wer.csv hp 2022-04-15
b43251044 op.xlsx fa 2022-04-15
b6512400 ip.csv jm 2022-04-15
b9123420 tb.xlsx tp 2022-04-15
b3214563 cv.txt ux 2022-04-14
There is no natural order of rows in a relational database (like there is in a spreadsheet). See:
Select last n rows without use of order by clause
Deterministic sort order for window functions
Assuming an id column to establish the order of rows that you seem to take for granted (and is not), this would work:
SELECT (t).*
FROM (
SELECT t, count(*) FILTER (WHERE source = 'hp') OVER (ORDER BY id) AS hp_ct
FROM tbl t
) sub
WHERE hp_ct BETWEEN 1 AND 2;
db<>fiddle here
You seem to want all rows starting with the first instance of source = 'hp' and stopping at the 3rd instance of the same. So do a running count in the subquery sub, and then filter all rows with count 1 & 2.
I work with a table alias t to grab the whole row and decompose in the outer SELECT to get rid of the added hp_ct without spelling out all column names. That's optional.

How to select rows where fields change

I have data similar to the following:
Version
ID
Reviewer
Action
Decision_Type
Review_start_time
Review_end_time
3
ABC123
Bob
Approve
Reactive
2021-03-31 16:49:16.0
2021-03-31 20:10:06.0
2
ABC123
Bob
Block
Pre-Publish
2021-03-31 16:49:16.0
2021-03-31 20:09:29.0
1
ABC123
System
InProgress
Pre-Publish
2021-03-31 16:49:16.0
2021-03-31 17:50:52.0
I need to be able to query IDs where:
The reviewer was Bob
Changes from Action = Block & Decision_Type = Pre-Publish to Action = Approve & Decision_Type = Reactive
(NOTE: the version numbers will change depending on how many reviews were completed, this is just an example)
You can join the table to itself on the ID and Reviewer and test for the presence of both kinds of records:
Select b.id, b.reviewer
From MyTable b Inner Join MyTable a On b.id=a.id and b.reviewer=a.reviewer
Where b.Action = 'Block' and b.Decision_Type = 'Pre-Publish'
and a.Action = 'Approve' and a.Decision_Type = 'Reactive'
and b.review_end_time<a.review-end-time
I added a requirement to the Where to ensure Approve came after Block using review end. Based on your comment it seems you cannot be certain that the Approve' comes directly after, just somewhere after.

SQL command to filter based on multiple tables and criteria

I am trying to learn sql, its driving me nuts. I cannot seem to grasp the proper syntax to achieve my desired output. I am watching videos on udemy and reading books on basic sql trying to teach myself, but it seems they all fall short in helping me bridge this gap I seem to not be able to over come.
I have a pretty good handle on the basics of the SELECT, FROM, WHEN commands. I seem to be gaining knowledge on using aggregate functions, but I am by no means an expert.
I have two tables, "Orders" and "OrderDet". "Orders" contains the CustomerName and the OrderNo, and OrderDet contains everything else, like PartNo, DateFinished, OrderNo, etc.
I have a situation where I can have multiple customers order the same part number. I want to show all the last orders all customers placed.
For example
SELECT Orders.CustDesc, OrderDet.OrderNo, OrderDet.PartNo, OrderDet.DateFinished
FROM Orders
JOIN OrderDet ON Orders.OrderNo = OrderDet.OrderNo
ORDER BY OrderDet.PartNo, OrderDet.DateFinished
This query returns:
Customer OrderNo PartNo Date Finished
--------------------------------------------------------
Cust 1 5032 12345678-1 NULL
Cust 2 10032 12345678-1 2019-06-05 14:54:25.853
Cust 2 1048 12345678-1 2019-07-08 00:00:00.000
Cust 1 5028 12345678-1 2019-09-30 11:45:45.960
Cust 1 5029 12345678-1 2019-09-30 12:49:35.713
Cust 1 5030 12345678-1 2019-09-30 13:04:57.333
Cust 1 5031 12345678-1 2019-10-10 13:58:22.653
I'm still learning when and how to use aggregate function but seem to not be able to fully grasp the concept. I tried to use a MAX on the Date column and GROUP BY the Customer and PartNo, but unless I remove the Order Number, the output never collapses down to what I want.
For example I used:
SELECT Orders.CustDesc, OrderDet.PartNo, MAX(OrderDet.DateFinished)
FROM Orders
JOIN OrderDet ON Orders.OrderNo = OrderDet.OrderNo
GROUP BY Orders.CustDesc, OrderDet.PartNo
ORDER BY OrderDet.PartNo
Removing OrderDet.OrderNo from SELECT, and OrderDet.DateFinished from the Order By.
This returns the row output I desire, but lacking all the columns I want.
Customer PartNo Date Finished
--------------------------------------------
Cust 2 12345678-1 2019-07-08 00:00:00.000
Cust 1 12345678-1 2019-10-10 13:58:22.653
As soon as I try and add the OrderNo back into the mix, I get the same output as the first. I think I understand why this is happening because all the OrderNo's are unique and cannot get grouped, but I cant grasp how to over come this.
I understand this is a basic SQL command but I cannot seem to understand how to get the output I desire. In this example I wanted to only see the two rows of unique Customers based on the last date the PartNo was finished, but have the entire rows contents shown. Not just three columns.
Again, I am trying to learn this stuff and I can only read and re-read the same basic content to learn how to do this for so long. Everything I read seems to lack the info my brain seems to require for that "AH HA" moment.
Perhaps someone could help bridge this gap?
I am interpreting your question as wanting the most recent order for a given customer for each part that customer has ordered.
For this, I would recommend window functions:
select CustDesc, OrderNo, od.DateFinished
from (select o.custdesc, od.orderno, od.partno, od.datefinished,
row_number() over (partition by o.custdesc, od.partno order by od.datefinished desc) as seqnum
from Orders o join
orderdet od
on o.OrderNo = od.OrderNo
) od
where seqnum = 1;
order by od.PartNo, od.DateFinished

SQL one to many with conditions

I'm working with two tables:
table one : order_table
table two: order_details
order_table:
- Order ID (pk)
- Submitter
- Date
order_detail:
- Order_detail_id (unique, auto generated)
- parent_order (fk, points to the order_id this line is part of)
- date
- assigned_to (i.e. department1, department2, department3, department4)
etc.
One order can have multiple order details
For instance
Order_detail_id parent_order assigned_to
0000001 0010 department1
0000002 0010 department2
0000003 0010 department1
0000004 0010 department1
0000005 0011 department1
0000006 0011 department2
0000007 0011 department3
As you can see, an order can be assigned back and forth between departments.
What I’m trying to do is to get a list of all the orders that were never assigned to a specific department regardless of how many times they were assigned back and forth.
For instance, all the unique order numbers that were never assigned at any point to department2
So far I’m getting either nothing or all data that includes assignment de department2…
I've tried so many different ways and I'm unable to get the expected results. thanks for your help
Here is one way to get orders that were never assigned to a specific department:
select od.parent_order
from order_detail od
group by od.parent_order
having sum(case when assigned_to = 'department2' then 1 else 0 end) = 0;
I like this method because it is quite general. In your case, the following is probably more efficient:
select o.*
from orders o
where not exists (select 1
from order_details od
where od.parent_order = o.orderid and
od.assigned_to = 'department2'
);