Add dynamic column in select query - MS SQL - sql-server

Im using Ms SQL database,
My table looks,
SrNo Emp_ID Date Time
------------------------------------
1 25 03-Sep-12 9:35:35 AM
2 25 03-Sep-12 10:31:32 AM
3 25 03-Sep-12 10:34:13 AM
4 25 03-Sep-12 11:05:08 AM
5 25 03-Sep-12 11:08:39 AM
6 25 04-Sep-12 09.05.40 AM
The expected output is
SrNo Emp_ID Date Time Type
---------------------------------------------
1 25 03-Sep-12 9:35:35 AM IN
2 25 03-Sep-12 10:31:32 AM OUT
3 25 03-Sep-12 10:34:13 AM IN
4 25 03-Sep-12 11:05:08 AM OUT
5 25 03-Sep-12 11:08:39 AM IN
6 25 04-Sep-12 09.05.40 AM IN
For an employee, type "in" and "out" has to be added simultaneously for particular date. For the next date or next /same employee, type has to start with "IN". Can any 1 help me in writing the sql query.

You can achieve this using an additional column
ROW_NUMBER() OVER (PARTITION BY Emp_ID, Date ORDER BY Time) AS RN
then checking modulus 2 on it, if remainder is 1, it's an IN, if it's 0 it's an OUT, based on your requirements.
More specifically
CASE WHEN
ROW_NUMBER() OVER (PARTITION BY Emp_ID, Date ORDER BY Time) % 2 = 1
THEN 'IN'
ELSE 'OUT'
END AS [Type]

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

Return Maximum Value along with day + time value grouped by month

Using MS-SQL 2012. Having a real puzzle trying to retrieve specific datafields from a large climatology dataset.
I have stripped this large raw data file down to a temp table called #max_temp which correctly pulls back the max value for each day along with the time it occurred and day/month value for reference:
monthid month day time current_temp
1 12 24 12:45 9.1
1 12 25 12:25 8.3
1 12 26 23:55 8.6
1 12 27 00:00 8.6
1 12 28 13:15 5.9
1 12 29 12:50 5
1 12 30 13:32 6.3
1 12 31 12:49 6.9
2 1 1 23:59 12
2 1 2 01:12 12.7
2 1 3 03:55 6.2
What I want to retrieve is an output grouped by monthID, so returning:
monthid month day time current_temp
1 12 24 12:45 9.1
2 1 9 20:04 15.1 <<*not shown in above sample*>>
From looking at other similar questions I have tried the following the code but not getting to the end solution or the query fails.
select *
from (select t.*, ROW_NUMBER () over (partition by t.monthid, t.time order by t.current_temp desc) as rn
from #max_temp t) x
where rn=1
order by monthid asc
or
select monthid, day, time, current_temp
from #max_temp
where current_temp= (select max(current_temp) from #max_temp group by MonthID, day, time)
Thanks in advance for your help,
Elliot.
Remove t.time from the partition by like so:
select *
from (
select t.*, ROW_NUMBER () over (partition by t.monthid order by t.current_temp desc) as rn
from #max_temp t
) x
where rn=1
order by monthid asc
Having time in the partition would give you the greatest value for current_temp for each monthid and time, but since you just want the greatest current_temp for each monthid, remove time from that expression.

get record according to date

I try this query according to date i have only column datecurrent in this record according to current date so there is almost 5 days record with different dates now i want to fetch record according to date i use this but this shows all records whereas i want to get record in specific dates
select c.Orderid,c.DateCurrent,c.Quantity,c.ItemCost,i.ItemCost*c.quantity
as Bill from CustomerOrder c inner join item i on i.ItemId=c.ItemId
inner join userinformation ui on ui.userid=c.userid
where c.datecurrent as fromdate > '2017-04-13' union all
select null,null,null,null,sum (i.ItemCost*c.Quantity) bill
from CustomerOrder c inner join item i on i.itemid=c.ItemId
inner join userinformation ui on ui.userid=c.userid where c.datecurrent as todate > '2017-04-15'
there is records of 16 date and above query shows 16 date records where i want only those records which is between 13 and 15 and same with other dates .. i try this query in winforms with datepicker
this is data
Orderid DateCurrent Quantity ItemCost Bill
101 2017-04-16 14:35:45.823 12 10 120
1093 2017-04-16 17:32:36.250 2 10 20
2093 2017-04-16 17:32:36.250 2 10 20
2094 2017-04-13 17:32:36.250 4 10 400
2095 2017-04-15 17:32:36.250 5 10 50
2096 2017-04-15 17:32:36.250 10 10 1000
2097 2017-04-14 17:32:36.250 12 10 120
NULL NULL NULL NULL 1210
this is i want to get data if i enter only dates between 13 and 15
Orderid DateCurrent Quantity ItemCost Bill
2094 2017-04-13 17:32:36.250 4 10 400
2095 2017-04-15 17:32:36.250 5 10 50
2096 2017-04-15 17:32:36.250 10 10 1000
2097 2017-04-14 17:32:36.250 12 10 120
NULL NULL NULL NULL 1210
I suspect that this does what you want:
select c.DateCurrent, sum(i.ItemCost * c.quantity) as Bill
from CustomerOrder c inner join
item i
on i.ItemId = c.ItemId
where c.datecurrent >= '2017-04-13'
group by grouping sets ( (c.DateCurrent), () );
This returns one row per date plus the total of all dates, along with the sum of the cost times quantity.

Custom ordering of records in SQL Server

I have a table such as http://sqlfiddle.com/#!6/e4f6f which contains records that need to be reported on an Excel using SSIS.
However, the ordering of records needs to be custom.
Such as below
AID BID CID CurrencyID ClassID Year MetricID Value ReferenceID
220 1 3 6 1147 2012 C1 653465.751842658967 V001
220 1 3 6 1147 2012 C2 0.000000000000 V001
220 1 3 6 1156 2012 C1 1151019.50078003120 V001
220 1 3 6 1156 2012 C2 0.000000000000 V001
As you can see the records are grouped such that they are ordered on ReferenceID first and then all the other dimension keys except the MetricID. Any help is much appreciated
Put MetricID as the last column in your ORDER BY:
SELECT *
FROM [FactValidationResult]
ORDER BY
ReferenceID,
AID,
BID,
CID,
CurrencyID,
Year,
ClassID,
MetricID

SQL Server: How to get a rolling sum over 3 days for different customers within same table

This is the input table:
Customer_ID Date Amount
1 4/11/2014 20
1 4/13/2014 10
1 4/14/2014 30
1 4/18/2014 25
2 5/15/2014 15
2 6/21/2014 25
2 6/22/2014 35
2 6/23/2014 10
There is information pertaining to multiple customers and I want to get a rolling sum across a 3 day window for each customer.
The solution should be as below:
Customer_ID Date Amount Rolling_3_Day_Sum
1 4/11/2014 20 20
1 4/13/2014 10 30
1 4/14/2014 30 40
1 4/18/2014 25 25
2 5/15/2014 15 15
2 6/21/2014 25 25
2 6/22/2014 35 60
2 6/23/2014 10 70
The biggest issue is that I don't have transactions for each day because of which the partition by row number doesn't work.
The closest example I found on SO was:
SQL Query for 7 Day Rolling Average in SQL Server
but even in that case there were transactions made everyday which accomodated the rownumber() based solutions
The rownumber query is as follows:
select customer_id, Date, Amount,
Rolling_3_day_sum = CASE WHEN ROW_NUMBER() OVER (partition by customer_id ORDER BY Date) > 2
THEN SUM(Amount) OVER (partition by customer_id ORDER BY Date ROWS BETWEEN 2 PRECEDING AND CURRENT ROW)
END
from #tmp_taml9
order by customer_id
I was wondering if there is way to replace "BETWEEN 2 PRECEDING AND CURRENT ROW" by "BETWEEN [DATE - 2] and [DATE]"
One option would be to use a calendar table (or something similar) to get the complete range of dates and left join your table with that and use the row_number based solution.
Another option that might work (not sure about performance) would be to use an apply query like this:
select customer_id, Date, Amount, coalesce(Rolling_3_day_sum, Amount) Rolling_3_day_sum
from #tmp_taml9 t1
cross apply (
select sum(amount) Rolling_3_day_sum
from #tmp_taml9
where Customer_ID = t1.Customer_ID
and datediff(day, date, t1.date) <= 3
and t1.Date >= date
) o
order by customer_id;
I suspect performance might not be great though.

Resources