T-SQL query to write case statements with different scenarios - sql-server

I have 2 tables Test Table and Investigation table.
Test table has
ChildID AddressID TestID TestValue TestDate
1 1 1 20 08/04/2017
2 2 2 20 09/04/2017
2 2 3 10 10/04/2017
When a child has test value >=20 the system automatically generates a Investigation on address but cannot open when between 15 and 19.9
Investigation Table
ChildID InvestID AddressID Status
1 1 1 open
2 2 2 open
If I get a new incoming Test record for child id's this is how my table looks
ChildID AddressID TestID TestValue TestDate
1 1 1 20 08/04/2017
1 5 4 16 12/04/2017(New record)
2 2 2 20 09/04/2017
2 2 3 10 10/04/2017
2 3 5 19 12/04/2017(New Record)
Scenario 1
I want to select New records and show 'status'(new column) as 'New address' case where Test value is between 15 and 19.9 and test date is 90 days apart and address id is not equal for two tests. Don't select any record if the address is same.
Scenario 2
If the child has second testvalue between 15 and 19.9 with same addess id
ChildID AddressID TestID TestValue TestDate
3 6 10 16 08/04/2017
3 6 20 18 11/04/2017 (New Record)
Select the new records with status as 'New Case and New address'
Scenario 3
ChildID AddressID TestID TestValue TestDate
3 6 10 16 08/04/2017
3 6 20 18 11/04/2017
3 7 21 17 02/04/2018 (New record)
Show latest record status as 'new address' because it has different address.
So far I have written the query but I am unable to compare records and write case statements for 'Status column'. I am only able to select records.
Select childid,Testid,TestDate,
TestValue,addressid,lc.caseType,
DateDiff(Day,lead(Test) OVER (Partition by Childid order by TestDate desc),Testdate) as Datediff,
DateDiff(day,First_Value(Testdate) Over (Partition by Childid order by b2.Testdateasc),Testdate) as Datedif1
from Test T
Left Join Investigation I
on T.child=I.childid
and b.observationValue between 15 and 19.99
and Datedif1>=90 or Datediff>=90

Related

Linking tables on date basis

I am having two tables as below
Child_Attendance
childid updatedon presentdays
1 31/01/2018 20
1 28/02/2018 15
1 31/03/2018 18
1 30/04/2018 24
1 31/05/2018 17
1 30/06/2018 19
2 31/03/2018 25
2 30/04/2018 28
2 31/05/2018 22
2 30/06/2018 23
And the Second table as
childid class admissiondate
1 creches 15/06/2017
1 balwari 01/02/2018
2 creches 01/01/2017
2 balwari 01/01/2018
2 Bridge Course 01/04/2018
Now, I need a query to return childid,updatedon,presentdays,class.
I am new to sql and don't have any idea how to do it.
I have tried
SELECT t1.childid,t1.updatedon,t1.presentdays,t2.class
FROM child_attendance t1 LEFT JOIN class_allocation t2
ON t1.childid = t2.childid
AND t1.updatedon >= t2.admissiondate
My output should be like this
You can see the child 1 was admitted in creche on dated 15/06/2017 and balwari on dated 01/02/2018. This means he was in creche from 15/06/2018 till 01/02/2018.
I think this query could get what you want:
SELECT t1.childid, t1.updatedon, t1.presentdays,
class=(SELECT TOP (1) class
FROM Class_Allocation
WHERE childid=t1.childid
AND t1.updatedon>=admissiondate
ORDER BY admissiondate DESC)
FROM Child_Attendance t1

SQL Server 2008 - merge rows when condition matched

I am running a stored procedure and getting the following value.
Name ID NewID Qty Rqty Total
Test1 1 5 4 9
Test2 10 1001 3 0 3
Test2 1001 4 2 6
Test3 15 1005 0 0 0
Test3 1005 3 4 7
If you look the Test3, where first id 15 has a new id 1005 But the Qty and Rqty is 0, next line I am getting ID 1005 and Qty, Rqty 3 and 4, total 7and this is correct.
What I am trying to do is when any ID got a new ID and Qty, Rqty both are 0, I need the following output in on row
Test3 15 1005 3 4 7
So, my final results will be -
Name ID NewID Qty Rqty Total
Test1 1 5 4 9
Test2 10 1001 3 0 3
Test2 1001 4 2 6
Test3 15 1005 3 4 7
My stored procedure is -
select Name, ID, NewID, Qty, RQty, SUM(Qty + RQty) as Total
from table1
Group By Name, ID, NewID, Qty, RQty
Order by Name
Could anyone help to solve this issue please.
Thanks
You will need to generate a psuedo "grouping" ID and NewID based on your conditions, group on those fields and select the MIN and MAX of the original ID and NewID along with aggregates of your other values. e.g.
CREATE TABLE dbo.Tests
(
Name varchar(10),
ID int,
[NewID] int NULL,
Qty int,
Rqty int
);
INSERT dbo.Tests (Name,ID,[NewID],Qty,Rqty)
--VALUES ('Test1',1,NULL,5,4)
-- ,('Test2',10,1001,3,0)
-- ,('Test2',1001,NULL,4,2)
-- ,('Test3',15,1005,0,0)
-- ,('Test3',1005,NULL,3,4);
VALUES ('test1',1,101,0,0)
,('test1',101,NULL,2,4)
,('test2',2,102,0,0)
,('test2',102,NULL,4,5)
,('test3',3,103,0,0)
,('test3',103,NULL,3,3)
,('test4',4,104,0,0)
,('test4',104,NULL,1,3)
,('test5',5,105,0,0)
,('test5',105,NULL,3,6);
SELECT t.Name,
min(t.ID) AS ID,
max(t.[NewID]) AS [NewID],
sum(t.Qty) AS Qty,
sum(t.Rqty) AS Rqty,
sum(t.Qty)+sum(t.Rqty) AS Total
FROM dbo.Tests AS t
CROSS APPLY (VALUES(CASE WHEN Qty = 0 AND Rqty = 0 AND t.[NewID] IS NOT NULL THEN [NewID] ELSE ID END,
CASE WHEN Qty = 0 AND Rqty = 0 AND t.[NewID] IS NOT NULL THEN -1 ELSE coalesce([NewID],-1) END)
) x(GroupingID, GroupingNewID)
GROUP BY Name,x.GroupingID,x.GroupingNewID
ORDER BY Name,max(t.ID);

Stored procedure for nested subquery in SQL Server 2008

I am in need of stored procedure, I have searched but I didn't get any relevant code.
My requirement is the stored procedure wants to loop the first subquery based on inner subquery.
Select *
from StockInward,
Setup
where StockInward.StockLocation=Setup.Id
AND ProductId in( Select ProductId
from ProductOutward
where Orderid ='38')
The sample table data and output below:
Product Outward table
Id Orderid Productid Qty
1 38 7 2
2 38 6 1
Stockinward table
Id ProductId BranchId Qty
1 7 1 12
2 6 1 2
3 7 2 2
Setup table
BranchId Branchname
1 Xyz
2 ABC
The output need to be:
ProductId Branches
7 Xyz(12) Abc(2 )
6 Xyz(2) -

SQL Server Multiple Counts in the same Query

I'm sure there is an easy way to do this but I've been struggling with this one...
Suppose I have an order table like so:
OrderId OrderStatus DriverId TripId
------- ----------- ------ ----
1 Available 5 2
2 Available 5 2
3 Available 5 2
4 Delivered 5 2
5 Delivered 5 3
6 Delivered 6 2
I want to group by each Driver and Trip with an extra column displaying the count of the OrderStatus when it is equal to 'Available'. So, for example
TotalOrderCountInTrip DriverId TripId AvailableOrdersCount
--------------------- -------- ------ --------------------
4 5 2 3
1 6 2 0
I've gotten this far but I can't figure out how to add the AvailableOrdersCount column:
select count(*) TotalOrderCountInTrip, dos.DriverId, dos.TripId
from DriverOrderSet dos (nolock)
group by
dos.DriverId,
dos.TripId
Add as a column:
sum(case when OrderStatus = 'Available' then 1 else 0 end)

Transact SQL - which Join to Use

I have two simple SELECT statements:
The first shows a list of Features.
SELECT * FROM Features
id name
-- ----
1 24 Hour Access
2 24 hour CCTV monitoring
3 Airport location
4 Break-Out Areas
5 Business Lounge
6 Business park location
snip..
and the second statement shows a list of feature information that has changed
SELECT
*
FROM
#SmartFeaturesToUpdate new_features
ORDER BY
new_features.centre_translation_id,
new_features.feature_id,
new_features.feature_selected
feature_id centre_translation_id feature_selected
---------- --------------------- ----------------
1 1 1
2 1 1
5 1 1
10 1 1
11 1 1
snip..
What I want to see is all of the features by centre translation.
Combining the tables gives me:
SELECT
*
FROM
#SmartFeaturesToUpdate new_features
LEFT JOIN Feature feature ON feature.id = new_features.feature_id
ORDER BY
new_features.centre_translation_id,
new_features.feature_id,
new_features.feature_selected
feature_id centre_translation_id feature_selected id name
---------- --------------------- ---------------- -- ----
1 1 1 1 24 Hour Access
2 1 1 2 24 hour CCTV monitoring
5 1 1 5 Business Lounge
10 1 1 10 Double Glazing
11 1 1 11 Elevator
snip..
The result above is missing feature id's 3 and 4, because they are not in the second list.
but the result I need is:
feature_id centre_translation_id feature_selected id name
---------- --------------------- ---------------- -- ----
1 1 1 1 24 Hour Access
2 1 1 2 24 hour CCTV monitoring
3 1 1 3 Airport Location
4 1 1 4 Break-Out Area
5 1 1 5 Business Lounge
snip..
How should I modify the third SELECT statement to acheive this and combine the results from both the features and feature information list?
As the comments alluded, I needed another table which linked Features to centre_translation_ids
First get all of the feature / centre_translation varients
SELECT
[centre_translation_id] = centre_translation.id,
feature.id,
feature.name
INTO #AllTheFeatures
FROM
CentreTranslation centre_translation
CROSS JOIN Feature feature
ORDER BY
centre_translation.id,
feature.id
Now we can simply perform the LEFT JOIN
SELECT
all_features.centre_translation_id,
all_features.id,
all_features.name,
smart_features.feature_selected
FROM
#AllTheFeatures all_features
LEFT JOIN #SmartFeaturesToUpdate smart_features ON smart_features.centre_translation_id = all_features.centre_translation_id AND
smart_features.feature_id = all_features.id
ORDER BY
all_features.centre_translation_id,
all_features.id
This gives the results:
centre_translation_id id name feature_selected
--------------------- -- ---- ----------------
1 1 24 Hour Access 1
1 2 24 hour CCTV monitoring 1
1 3 Airport location NULL
1 4 Break-Out Areas NULL
1 5 Business Lounge 1
Why don't you just put it in one query?
SELECT
centre_translation.id AS centre_translation_id,
feature.id,
feature.name,
smart_features.feature_selected
FROM
CentreTranslation centre_translation
CROSS JOIN Feature feature
LEFT JOIN #SmartFeaturesToUpdate smart_features
ON smart_features.centre_translation_id = all_features.centre_translation_id
AND smart_features.feature_id = all_features.id
ORDER BY
centre_translation.centre_translation_id,
feature.id

Resources