sql server pivot using date to order data in columns - sql-server

My tables combined look something like:
Seller_ID |From |To |Depart_Date |Arrival_Date
-------------------------------------------------------------------------------------
Paul |office |client_23 |10/20/2015 3:30:00 PM |10/21/2015 7:54:00 AM
Paul |client_23 |client_ 88fe |10/21/2015 11:55:00 AM |10/22/2015 8:11:00 PM
Paul |client_88fe |client_avr4 |10/23/2015 3:57:00 PM |10/26/2015 11:27:00 AM
Paul |client_avr4 |home |10/26/2015 5:28:00 PM |10/28/2015 3:39:00 PM
I do not have a indicator like first visit, second visit, third visit...
First visit always has 'From' = office and last visit always has 'To' = home.
Only way to make the sequence is either go backwards by Dates (or by From-To ??)
My desired outcome would be :
|Seller_ID |from |office_departure |client1 |clt1_arrival |clt1_departure |client2 |clt2_arrival |clt2_departure |client3 |clt3_arrival |clt3_departure |home_arrival
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|Paul |office |10/20/2015 3:30:00PM |client_23 |10/21/2015 7:54:00 AM|10/21/2015 11:55:00 AM |client_ 88fe|10/22/2015 8:11:00 PM |10/23/2015 3:57:00 PM |client_avr4 |10/26/2015 11:27:00 AM |10/26/2015 5:28:00 PM |10/26/2015 5:28:00 PM
Any help is apreciated!
thanks in advance.

If your case is just one trip per seller, or that you have another field not shown here that you can use in group by, you can use something like this:
select
Seller_ID,
max(case when RN = 1 then [From] end),
max(case when RN = 1 then [Depart_Date] end),
max(case when RN = 1 then [Arrival_Date] end),
max(case when RN = 2 then [From] end),
max(case when RN = 2 then [Depart_Date] end),
max(case when RN = 2 then [Arrival_Date] end)
from (
select
row_number() over (partition by Seller_ID
order by Depart_Date asc) as RN,
*
from Table1
) X
group by Seller_ID
Result:
Seller_ID
Paul office October, 20 2015 15:30:00 October, 21 2015 07:54:00 client_23 October, 21 2015 11:55:00 October, 22 2015 20:11:00
Example in SQL Fiddle
If you don't have any field for tracking the number of trip, you can use running total in order of departure date for statement case when [From] = 'office' then 1 else 0 end partitioned by Seller_ID, that will then assign trip number for the rows.

Related

SQL query to fetch all results in one query

Test data:
id date company location
----------------------------------
1 03/01/2016 ABC india
2 03/25/2016 ABC us
3 02/24/2016 ABC india
4 02/25/2016 ABC us
5 03/02/2016 ABC india
Query #1
select count(id)
from table
where company = 'ABC'
and date between 03/01/2016 and 03/31/2016
Query #2
select count(id)
from table
where company = 'ABC'
and date between 02/01/2016 and 02/29/2016
Need to calculate location wise count for current and previous months.
How to write a SQL query to return location wise like the below in one query?
Expected result:
company currentmonth Previousmonth location
ABC 2 1 india
ABC 1 1 us
Try:
select company,
sum(case when month(date)=month(getdate())
then 1 else 0 end) as currentMonth,
sum(case when month(date)=month(dateadd(MONTH,-1,getdate()))
then 1 else 0 end) as Previuosmonth,
location
from yourTable
where month(date) between month(dateadd(MONTH,-1,getdate())) and month(getdate())
AND company='ABC'
group by company, location
Since you made two queries and filter both with current month (march) and previous. I decided to use the function MONTH to extract the month from the current date (getdate()) of the system and subtract 1 that way you will always have the current month and the previous one.
EDIT
As pointed out by #DhananjayaKuppu I fixed the problem for when you have a month as January, since the month function returns an integer it would return 0 in my calculation. Now it is fixed.
You may try some thing like subtract current date yearmm format (ex: 201603) and yearmm format of date from table (ex:201603) if it result to 0 treat as current month, else previous month, hope it will help:
SELECT company,
location,
sum(iif(d = 0, 0, 1)) cm,
sum(iif(d = 0, 1, 0)) pm
FROM (SELECT company,
location,
CONVERT(INT,
CONVERT(CHAR(4), GetDate(), 120) +
CONVERT(CHAR(2), GetDate(), 101)
) -
CONVERT(INT,
CONVERT(CHAR(4), date, 120) +
CONVERT(CHAR(2), date, 101)
) as d
FROM table) vw
GROUP BY company, location

T-SQL Query to remove duplicate records in the output based on one particular column

I am running SQL Server 2014 and I have the following T-SQL query:
USE MYDATABASE
SELECT *
FROM RESERVATIONLIST
WHERE [MTH] IN ('JANUARY 2015','FEBRUARY 2015')
RESERVATIONLIST mentioned in the code above is a view. The query gives me the following output (extract):
ID NAME DOA DOD Nights Spent MTH
--------------------------------------------------------------------
251 AH 2015-01-12 2015-01-15 3 JANUARY 2015
258 JV 2015-01-28 2015-02-03 4 JANUARY 2015
258 JV 2015-01-28 2015-02-03 2 FEBRUARY 2015
The above output consist of around 12,000 records.
I need to modify my query so that it eliminates all duplicate ID and give me the following results:
ID NAME DOA DOD Nights Spent MTH
--------------------------------------------------------------------
251 AH 2015-01-12 2015-01-15 3 JANUARY 2015
258 JV 2015-01-28 2015-02-03 4 JANUARY 2015
I tried something like this, but it's not working:
USE MYDATABASE
SELECT *
FROM RESERVATIONLIST
WHERE [MTH] IN ('JANUARY 2015', 'FEBRUARY 2015')
GROUP BY [ID]
HAVING COUNT ([MTH]) > 1
Following query will return one row per ID :
SELECT * FROM
(
SELECT *,ROW_NUMBER() OVER (PARTITION BY ID ORDER BY (SELECT NULL)) rn FROM RESERVATIONLIST
WHERE [MTH] IN ('JANUARY 2015','FEBRUARY 2015')
) T
WHERE rn = 1
Note : this will return a random row from multiple rows having same ID. IF you want to select some specific row then you have to define it in order by. For e.g. :
SELECT * FROM
(
SELECT *,ROW_NUMBER() OVER (PARTITION BY ID ORDER BY DOA DESC) rn FROM RESERVATIONLIST
WHERE [MTH] IN ('JANUARY 2015','FEBRUARY 2015')
) T
WHERE rn = 1
definitely, it will return the row having max(DOA).
You are trying to do a GROUP BY statement which IMHO is the right way to go. You should formulate all columns that are a constant, and roll-up the others. Depending on the value of DOD and DOA I can see two solutions:
SELECT ID,NAME,DOA,DOD,SUM([Nights Spent]) as Nights,
min(MTH) as firstRes, max(MTH) as lastRes
FROM RESERVATIONLIST
GROUP BY ID,NAME,DOA,DOD
OR
SELECT ID,NAME,min(DOA) as firstDOA,max(DOD) as lastDOD,SUM([Nights Spent]) as Nights,
min(MTH) as firstRes, max(MTH) as lastRes
FROM RESERVATIONLIST
GROUP BY ID,NAME

Gap Between two two dates of different cells

I need help to create one script where i got stuck.
MemberId BeginDate EndDate Output
1039725910 3/1/2014 8/10/2014 0 End on 10th August
1039725910 8/11/2014 11/10/2014 1 Start on 11th August, 1 day gap
1039725910 11/11/2014 12/31/2014 1 Start on 11th August, 1 day gap
1166164140 1/1/2014 4/30/2039 0 End on 30 April
1166164140 2/5/2014 12/30/2039 2 Start on 1st May, Here is a 2 days gap
Here For one member I have three different begin and end date. for the first records for each member, it would be 0, for the 2nd records, the gap would be (2nd Begindate - 1st EndDate). For 3rd record, The difference would be (3rd Begin date - 2nd EndDate) and so on...I am not able to attach any screenshot.
Kindly help me on this.
Regards,
Ratan
You can use the row_number() window function together with a self-join to access the previous row partitioned by MemberId like this:
select
a.MemberId,
a.BeginDate,
a.EndDate,
Output = ISNULL(DATEDIFF(DAY, isnull(b.EndDate, a.BeginDate), a.BeginDate), 0)
from
(select *, rn = ROW_NUMBER() over (partition by memberid order by begindate) from members) a
left join
(select *, rn = ROW_NUMBER() over (partition by memberid order by begindate) from members) b
on a.MemberId = b.MemberId and a.rn - 1 = b.rn
With your sample data this would give you:
MemberId BeginDate EndDate Output
1039725910 2014-03-01 2014-08-10 0
1039725910 2014-08-11 2014-11-10 1
1039725910 2014-11-11 2014-12-31 1
1166164140 2014-01-01 2039-04-30 0
1166164140 2014-05-02 2039-12-30 -9129
If you need to disregard the year component you'll have to do some date arithmetic.
You can use ROW_NUMBER()
Try using query like one given below:
select *,
case when rno = 1 then 0
else datediff(day, begindate,enddate) end as difference
from
(select *, row_number() over (partition by MemberId order by MemberId) as rno from members)
tbl
Check below demo code:
SQLFiddle Demo

Case When for Specific Criteria

I have a query that lists employees ratings throughout the years, but the years are all listed in one column. I am trying to get the meeting years to have their own columns with the score, and if they do not have a score for it to be null.
THe Code so far:
SELECT Employee_ID, Meeting_Year, Manager_Readiness_Rating
FROM dbo.v_sc17_TMS_Data_Career_Meeting_Rating
GROUP BY Employee_ID, Meeting_Year, Manager_Readiness_Rating
So if the meeting_year is 2012 I want all 2012 Manager_Readiness_Rating listed in the column for the employees. Here is some examples
ID Year Rating
1 2011 11
2 2012 10
3 2010 09
4 2010 03
4 2011 03
I would like it to look like
ID 2010 2011 2012
1 NULL 11 NULL
2 NULL NULL 1
3 09 NULL NULL
4 03 03 NULL
SELECT Employee_ID, Meeting_Year, GROUP_CONCAT(Manager_Readiness_Rating)
FROM dbo.v_sc17_TMS_Data_Career_Meeting_Rating
GROUP BY Employee_ID, Meeting_Year
This is flagged as MySQL, but the dbo makes me think it's SQL Server. This query should work for either one:
SELECT
Employee_ID AS ID,
MAX(CASE WHEN Year = 2010 THEN Rating END) AS R2010,
MAX(CASE WHEN Year = 2011 THEN Rating END) AS R2011,
MAX(CASE WHEN Year = 2012 THEN Rating END) AS R2012
FROM dbo.v_sc17_TMS_Data_Career_Meeting_Rating
GROUP BY Employee_ID
ORDER BY 1

Calculate total running time from start/stop timestamps

I have a table containing a number of timestamps per day, they represents start and stop events.
ID TimeStamp
----------------------
1 2008-01-01 07:00:00
1 2008-01-01 08:15:00
1 2008-01-01 10:00:00
1 2008-01-01 11:00:00
1 2008-01-02 10:30:00
1 2008-01-02 12:00:00
I would like to calcuate the total running time per day, like this:
ID Date RunningTime
-------------------------
1 2008-01-01 02:15:00
1 2008-01-02 01:30:00
Do anyone have a nice T-SQL solution for my problem?
WITH q AS
(
SELECT *,
CONVERT(DATETIME, CONVERT(VARCHAR(8), TimeStamp, 112), 112) AS dte,
ROW_NUMBER() OVER (PARTITION BY id, CONVERT(DATETIME, CONVERT(VARCHAR(8), TimeStamp, 112), 112) ORDER BY TimeStamp) AS rn
FROM mytable
)
SELECT qb.id, qb.dte, SUM(DATEDIFF(second, qb.TimeStamp, qe.TimeStamp))
FROM q qb
JOIN q qe
ON qe.id = qb.id
AND qe.dte = qb.dte
AND qe.rn = qb.rn + 1
WHERE qb.rn % 2 = 1
GROUP BY
qb.id, qb.dte
This assumes that every record open on a certain day should also be closed on the same day.

Resources