CREATE TABLE interview (uniqueID int identity(1,1),
date datetime,
recordtype int,
amount numeric(18, 4))
INSERT INTO interview values('6/30/13', 1, 27.95)
INSERT INTO interview values('5/20/13', 1, 21.85)
INSERT INTO interview values('5/22/13', 2, 27.90)
INSERT INTO interview values('12/11/12', 2, 23.95)
INSERT INTO interview values('6/13/13', 3, 24.90)
INSERT INTO interview values('6/30/13', 2, 27.95)
INSERT INTO interview values('5/20/13', 2, 21.85)
INSERT INTO interview values('5/22/13', 1, 27.90)
INSERT INTO interview values('12/11/12',1, 23.95)
INSERT INTO interview values('6/13/13', 3, 24.90)
INSERT INTO interview values('6/30/13', 3, 27.95)
INSERT INTO interview values('5/20/13', 3, 21.85)
INSERT INTO interview values('5/22/13', 2, 27.90)
INSERT INTO interview values('12/11/12', 1, 23.95)
INSERT INTO interview values('6/13/13', 1, 24.90)
How to get the following result? What would the query look like?
I was only able to get a partial to work, but my answer is not correct. I need to
somehow join the queries.
select distinct date, count(RecordType)as Count_unique1
from interview
where RecordType = '1'
group by date
select distinct date, count(RecordType)as Count_unique2
from interview
where RecordType = '2'
group by date
select distinct date, count(RecordType)as Count_unique3
from interview
where RecordType = '3'
group by date
select
date,
sum(case when RecordType = '1' then 1 else 0 end) as Count_unique1,
sum(case when RecordType = '2' then 1 else 0 end) as Count_unique2,
sum(case when RecordType = '3' then 1 else 0 end) as Count_unique3
from interview
group by date
Also in MSSQL you can use PIVOT
SELECT date, [1] AS Count_unique1,
[2] AS Count_unique2,
[3] AS Count_unique3
FROM (SELECT date,recordtype,amount FROM interview) p
PIVOT
(
COUNT (amount)
FOR recordtype IN ([1], [2], [3])
) AS pvt
ORDER BY pvt.date;
SQLFiddle demo
If RecordType is 1,2 and 3 in all cases this will be enough.
select date,
sum(RecordType = '1') as Count_unique1,
sum(RecordType = '2') as Count_unique2,
sum(RecordType = '3') as Count_unique3
from interview
group by date
Related
I need to pivot data in SQL Server 2008. Can someone please give me some pointers to look around?
My Raw data looks like as:
create table #tbl (
ServiceDesc_2 varchar(20), ListCode_2 varchar(10), LongestWaitingDays_2 int, AvgWaitingDays_2 int, TotalPatientsWaiting_2 int);
insert #tbl
select 'XYZ - Left Side', 'Booked', 67, 16, 38
union all
select 'XYZ - Left Side', 'UnBooked', 23, 6, 53
union all
select 'XYZ - Right Side', 'Booked', 14, 8, 2
union all
select 'XYZ - Right Side', 'UnBooked', 4, 3, 2
I am trying to achieve below:
You can prepare your data with cross apply to multiply the rows in order to replicate the columns.
Then you can perform a conditional aggregation to obtain the desired results.
Here is a sample query that should work:
;with c as
(
select ServiceDesc_2,col,val as measures,ListCode_2,ord
from #tbl
cross apply
(
values
('LongestWaitingDays_2' ,LongestWaitingDays_2 , 1)
,('AvgWaitingDays_2' ,AvgWaitingDays_2 , 2)
,('TotalPatientsWaiting_2',TotalPatientsWaiting_2, 3)
)
CS (col,val,ord)
)
select
ServiceDesc_2
,col as Measures
,MAX(case when ListCode_2='UnBooked' then measures else null end) as UnBooked
,MAX(case when ListCode_2='Booked' then measures else null end) as Booked
from c
group by ServiceDesc_2, col
order by ServiceDesc_2, max(ord)
Output:
Is there any way to calculate the time difference in SQL between rows within the same column based on the 'DOWN' and 'UP' values like this:
There are 3 scenarios(that I'm aware of):
Yellow, Orange and Green: there is a state_id 2(down) and after that a state_id 5(up), so the time difference needs to be calculated between the two rows;
Blue: there are multiple state_id 2(down) and after that one state_id 5(up), so the time difference needs to be calculated between the first row and last row;
Red: there is only a state_id 2(down) because it is still down with any update, so the time difference needs to be calculated till the end of the month.
I hope you can help me out.
Was first considering to use LAG for this.
But using a cummulative SUM, and the window version of MIN works also for more than 2 DOWN's:
-- test reference data
declare #State table (id int, state varchar(4));
insert into #State (id, state) values
(2,'DOWN'),
(5,'UP')
-- test data, using a table variable
declare #AlertState table (alert_id int identity(1,1), host_id int, state_time datetime, state_id int);
insert into #AlertState (host_id, state_time, state_id) values
(119, GetDate()-0.32, 2),
(119, GetDate()-0.31, 5),
(119, GetDate()-0.24, 2),
(119, GetDate()-0.23, 2),
(119, GetDate()-0.22, 2),
(119, GetDate()-0.21, 5),
(119, GetDate()-0.15, 5),
(119, GetDate()-0.11, 2);
-- The query
select alert_id, host_id, state_time, state_id,
diff_min = (
case
when state_id = 5 then
datediff(minute, min(state_time) over (partition by host_id, stategroup), state_time)
when state_id = 2 and stategroup is null then
datediff(minute, state_time, cast(EOMONTH(GetDate()) as datetime)+1)
end),
s.state
from (
select alert_id, host_id, state_time, state_id,
sum(case state_id when 5 then 1 end) over (partition by host_id order by state_time desc) as stategroup
from #AlertState
where state_id in (2,5)
) q
left join #State s on s.id = q.state_id
order by state_time, alert_id;
The way I did this before is
Select a.state_time as downtime,
(
select min(inner.state_time) from tablename downentry where
inner.state_time > outer.state_time and downentry.state='UP'
) as uptime
from tablename upentry
where state = 'DOWN'
Then you need to find the datediff between them, and if uptime is null, the datediff between downtime and 'endofmonth'
It's potentially quite poor performing, so I always wrote the answer out to a data warehouse, but think it gives the results you're asking for.
SQL2012+
You could try following solution:
SELECT y.group_id, host_id = MIN(host_id), start_time = MIN(state_time), end_time = MAX(state_time), diff_minute = DATEDIFF(MINUTE, MIN(state_time), MAX(state_time))
FROM (
SELECT *, group_id = SUM(x.new_group_start) OVER(ORDER BY x.host_id, x.state_time)
FROM (
SELECT *, new_group_start = IIF(a.state_id = 'DOWN' AND ISNULL(LAG(a.state_id) OVER(ORDER BY a.host_id, a.state_time), 'UP') = 'UP', 1, 0)
FROM #Alerts a
) x
) y
GROUP BY y.group_id
ORDER BY y.group_id
Demo
i have following table "vehicle_data" :
ID ALERT_TYPE VALUE
58 2 1
58 1 1
104 1 1
104 2 1
Here alert_type = 2 is for GPS value and alert_type=1 is for engine_value .
so if alert_type=2 and its value is =1 then it means its value is correct.
when alert_type=2 and its value is =0 then it means its value is wrong.
same for alert_type=1
so now here i want the following output:
ID gps engine_value
58 1 1
104 1 1
how can i perform this query??
You can do it like this.
SELECT ID
,CASE WHEN [ALERT_TYPE]=2 and [value ]=1 THEN 1 ELSE 0 END as gps
,CASE WHEN [ALERT_TYPE]=1 and [value ]=1 THEN 1 ELSE 0 END as engine
FROM vehicle_data
SELECT ID, alert_type=2 AS gps, alert_type=1 AS [engine] FROM vehicle_data WHERE value=1;
EDITED to account for your explanation of VALUE.
Schema
CREATE TABLE table3 (id int, ALERT_TYPE int)
INSERT table3 VALUES (58, 1), (58, 2), (104, 1), (104, 2)
Query
SELECT *
FROM (
SELECT ID
,ROW_NUMBER() OVER (
PARTITION BY id ORDER BY id
) AS row_num
,gps = CASE
WHEN ALERT_TYPE = 2
THEN 1
ELSE 0
END
,engine = CASE
WHEN ALERT_TYPE = 1
THEN 1
ELSE 0
END
FROM table3
) a
WHERE a.row_num = 1
Output
ID gps engine
58 1 0
104 0 1
One possible way using subqueries :
select
Ids.ID
, gps.VALUE 'gps'
, engine_value.VALUE 'engine_value'
from (select distinct ID from vehicle_data) Ids
left join
(select ID, VALUE from vehicle_data where ALERT_TYPE = 2) gps
on gps.ID = Ids.ID
left join
(select ID, VALUE from vehicle_data where ALERT_TYPE = 1) engine_value
on engine_value.ID = Ids.ID
[SQL Fiddle demo]
I hope this should work for you,
Select ID,sum(gps) as gps ,sum(engine) as engine from
(SELECT ID
,CASE WHEN [ALERT_TYPE]=2 and [value ]=1 THEN 1 ELSE 0 END as gps
,CASE WHEN [ALERT_TYPE]=1 and [value ]=1 THEN 1 ELSE 0 END as engine
FROM vehicle_data
)a
group by id
select x.id,x.alert_type as GPS,x.value as engine_value from (
select ID,alert_type,value,ROW_NUMBER() over (partition by id order by alert_type ) as Rnk from mytable
)x
where Rnk=1
Please check this query in SQL :
create table mytable (id int, alert_type int, value int);
insert into mytable (id, alert_type, value)
values (58, 2, 1),
(58, 1, 1),
(104, 1, 1),
(104, 2, 1);
SELECT distinct ID
,(select count (id) from mytable mt where mt.id=mytable.id and mt.[ALERT_TYPE]=2 and mt.[value ]=1) as gps
,(select count (id) from mytable mt where mt.id=mytable.id and mt.[ALERT_TYPE]=1 and mt.[value ]=1) as engine
FROM mytable
BASED ON YOUR QUESTION I BELIEVE YOU WANT THE DATA IN COLUMN AND TO SUIT YOUR REQUIREMENT I HAVE MADE A SQL FIDDLE WORKING - CODE IS ALSO MENTIONED BELOW -
HERE YOU GO WITH THE WORKING FIDDLE -
WORKING DEMO
SQL CODE FOR REFERNECE -
CREATE TABLE ALERTS (ID INT, ALERT_TYPE INT, VALUE INT)
INSERT INTO ALERTS VALUES (58,2,1)
INSERT INTO ALERTS VALUES (58,1,0)
INSERT INTO ALERTS VALUES (104,1,1)
INSERT INTO ALERTS VALUES (104,2,0)
CREATE TABLE ALERTSVALUE (ID INT, gps INT,engine INT)
INSERT INTO ALERTSVALUE VALUES (58,1,0)
INSERT INTO ALERTSVALUE VALUES (104,0,1)
SELECT A.ID,
CASE A.ALERT_TYPE WHEN 2 THEN 1 ELSE 0 END AS GPS,
CASE A.ALERT_TYPE WHEN 1 THEN 1 ELSE 0 END AS ENGINE_VALUE,
A.VALUE FROM ALERTS A WHERE A.VALUE = 1
EDIT BASED ON COMMENT - TO MERGE THE ROWS FOR BOTH GPS AND ENGINE_VALUE:
SELECT X.ID,X.ALERT_TYPE as GPS,X.VALUE as ENGINE_VALUE
FROM (
SELECT ID,ALERT_TYPE ,VALUE ,ROW_NUMBER() OVER (PARTITION BY ID ORDER BY alert_type ) AS [Rank] FROM ALERTS
)X
WHERE [Rank]=1
SQL FIDDLE DEMO
I have a table with following structure:
AuthorId, FollowersNumber, PublishDate, ...
What I need is to draw graph of a running total of FollowersNumber by periods. Tricky thing is that every author is counted only once. For example for following table:
AuthorId, FollowersNumber, PublishDate
1 100 '2013-01-01'
2 200 '2013-01-01'
3 200 '2013-01-02'
2 100 '2013-01-02'
4 60 '2013-01-03'
1 30 '2013-01-03'
Result must be:
2013-01-01 - 300 (100+200)
2013-01-02 - 500 (300+200)
2013-01-03 - 560 (500+60)
Now my SQL looks like (simplified):
SELECT 0, SUM (q.FollowersNumber) AS Y FROM
(SELECT FollowersNumber FROM dbo.Aggregate p WITH (NOLOCK) WHERE p.PublishDate BETWEEN #CurrentPeriod_0_Start AND #CurrentPeriod_0_End AND p.AuthorId not IN
(SELECT AuthorId FROM dbo.Aggregate WITH (NOLOCK) WHERE PublishDate BETWEEN #PreviousPeriod_0_Start AND #PreviousPeriod_0_End)) AS q
UNION
SELECT 1, SUM (q.FollowersNumber) AS Y FROM
(SELECT FollowersNumber FROM dbo.Aggregate p WITH (NOLOCK) WHERE p.PublishDate BETWEEN #CurrentPeriod_1_Start AND #CurrentPeriod_1_End AND p.AuthorId not IN
(SELECT AuthorId FROM dbo.Aggregate WITH (NOLOCK) WHERE PublishDate BETWEEN #PreviousPeriod_1_Start AND #PreviousPeriod_1_End)) AS q
etc.
After getting that data I count running total of FollowersNumber in C# code.
This query is monstrous and runs slow.
Is there any way to make it faster?
http://sqlfiddle.com/#!3/ff2cf/4
Get Totals history By dates. I don't understand your parameters in query
Possible this be helpful for you -
DECLARE #temp TABLE
(
AuthorId INT
, FollowersNumber INT
, PublishDate DATETIME
)
INSERT INTO #temp (AuthorId, FollowersNumber, PublishDate)
VALUES
(1, 100, '20130101'),
(2, 200, '20130101'),
(3, 200, '20130102'),
(2, 100, '20130102'),
(4, 60, '20130103'),
(1, 30, '20130103')
DECLARE
#CurrentPeriod_0_Start DATETIME
, #PreviousPeriod_0_Start DATETIME
, #CurrentPeriod_0_End DATETIME
, #PreviousPeriod_0_End DATETIME
, #CurrentPeriod_1_Start DATETIME
, #PreviousPeriod_1_Start DATETIME
, #CurrentPeriod_1_End DATETIME
, #PreviousPeriod_1_End DATETIME
SELECT 0, Y = SUM(p.FollowersNumber)
FROM #temp p
WHERE p.PublishDate BETWEEN #CurrentPeriod_0_Start AND #CurrentPeriod_0_End
AND NOT EXISTS(
SELECT 1
FROM #temp p2
WHERE p2.PublishDate BETWEEN #PreviousPeriod_0_Start AND #PreviousPeriod_0_End
AND p2.AuthorId = p.AuthorId
)
UNION ALL
SELECT 1, Y = SUM(p.FollowersNumber)
FROM #temp p
WHERE p.PublishDate BETWEEN #CurrentPeriod_1_Start AND #CurrentPeriod_1_End
AND NOT EXISTS(
SELECT 1
FROM #temp p2
WHERE p2.PublishDate BETWEEN #PreviousPeriod_1_Start AND #PreviousPeriod_1_End
AND p2.AuthorId = p.AuthorId
)
You can use this query instead of yours.
I wrote this query using CTE in SQL Server. I tested it on your data sample and worked fine.
WITH
RANKINGTABLE AS(
SELECT [AUTHORID]
,[FOLLOWERSNUMBER]
,[PUBLISHDATE]
,DENSE_RANK() OVER(PARTITION BY AUTHORID ORDER BY PUBLISHDATE) IRANK
FROM [TESTQUERY].[DBO].[AGGREGATE]
),
DAYSUM AS(
SELECT PUBLISHDATE, SUM([FOLLOWERSNUMBER]) DATESUM
FROM RANKINGTABLE
WHERE IRANK = 1
GROUP BY PUBLISHDATE
)
SELECT DS1.PUBLISHDATE,
(SELECT SUM(DS2.DATESUM) FROM DAYSUM DS2 WHERE DS2.PUBLISHDATE <= DS1.PUBLISHDATE) PTOTAL
FROM DAYSUM DS1
You can try this
SELECT 1, SUM(CASE WHEN PublishDate BETWEEN #PreviousPeriod_0_Start AND #PreviousPeriod_0_End
THEN NULL ELSE CASE WHEN PublishDate BETWEEN #CurrentPeriod_0_Start AND #CurrentPeriod_0_End
THEN FollowersNumber
END
END
) AS Y
FROM dbo.Aggregate WITH(NOLOCK)
UNION ALL
SELECT 0, SUM(CASE WHEN PublishDate BETWEEN #PreviousPeriod_1_Start AND #PreviousPeriod_1_End
THEN NULL ELSE CASE WHEN PublishDate BETWEEN #CurrentPeriod_1_Start AND #CurrentPeriod_1_End
THEN FollowersNumber
END
END
) AS Y
FROM dbo.Aggregate WITH(NOLOCK)
etc.
I have 3 queries and they work fine. There Queries are:
SELECT SUM(SALES)as NETSALES FROM Sales WHERE DOCREF='1'GROUP BY GEOCODE
above query results :
NETSALES
1
2
3
SELECT SUM(SALES)as FRESHRETURNS FROM Sales WHERE DOCREF='2'GROUP BY GEOCODE
above query results :
FRESHRETURNS
1
2
3
SELECT SUM(SALES)as SALESRETURNS FROM Sales WHERE DOCREF='3'GROUP BY GEOCODE
above query results :
SALESRETURNS
1
2
3
is there any way to combine these statements to get the result as
NETSALES | FRESHRETURNS | SALESRETURNS
1------1-------|-----------1-----------|--------1--------
2------2-------|-----------2-----------|--------2--------
3------3-------|-----------2-----------|--------3--------
You didn't mention if you are using MS Sql Server or Oracle, I am assuming MS :)
Make use of CASE and you can basically build a matrix with the result you want:
CREATE TABLE #t
(
Sale int,
DocRef varchar(1),
GeoCode varchar(1)
)
INSERT INTO #t(Sale, DocRef,GeoCode) VALUES(100, '1', 'A')
INSERT INTO #t(Sale, DocRef,GeoCode) VALUES(120, '1', 'A')
INSERT INTO #t(Sale, DocRef,GeoCode) VALUES(110, '2', 'B')
INSERT INTO #t(Sale, DocRef,GeoCode) VALUES(120, '2', 'B')
INSERT INTO #t(Sale, DocRef,GeoCode) VALUES(100, '3', 'C')
INSERT INTO #t(Sale, DocRef,GeoCode) VALUES(100, '3', 'C')
INSERT INTO #t(Sale, DocRef,GeoCode) VALUES(100, '3', 'A')
SELECT
CASE WHEN DocRef='1' THEN SUM(Sale) ELSE 0 END as NETSALES,
CASE WHEN DocRef='2' THEN SUM(Sale) ELSE 0 END AS FRESHRETURNS,
CASE WHEN DocRef='3' THEN SUM(Sale) ELSE 0 END AS SALESRETURNS
FROM
#t
GROUP BY
GeoCode,
DocRef
DROP TABLE #t
I think this works but I haven't tested. I'm adding a fake ID column, giving it value 'x' and joining the 3 result sets using this new ID:
select t.NETSALES, ta.FRESHRETURNS , tb.SALESRETURNS from
(SELECT 'x' as ID, SUM(SALES)as NETSALES FROM Sales WHERE DOCREF='1'GROUP BY GEOCODE,ID ) as t
inner join
(SELECT 'x' as ID, SUM(SALES)as FRESHRETURNS FROM Sales WHERE DOCREF='2'GROUP BY GEOCODE,ID) ta on ta.ID=t.ID
inner join
(SELECT 'x' as ID SUM(SALES)as SALESRETURNS FROM Sales WHERE DOCREF='3'GROUP BY GEOCODE,ID ) tb on tb.ID=t.ID
Probably terribly inefficient but works for me on Oracle
SELECT (SELECT SUM(SALES) FROM Sales WHERE DOCREF='1'GROUP BY GEOCODE) NETSALES,
(SELECT SUM(SALES) FROM Sales WHERE DOCREF='2'GROUP BY GEOCODE) FRESHRETURNS ,
(SELECT SUM(SALES) FROM Sales WHERE DOCREF='3'GROUP BY GEOCODE) SALESRETURNS FROM DUAL
Depending on which database product you are using, you may need to tweak this a bit, but something like this should work for you:
SELECT GEOCODE, SUM(NETSALES), SUM(FRESHRETURNS), SUM(SALESRETURNS)
FROM
(
SELECT GEOCODE, SUM(SALES)as NETSALES, 0 AS FRESHRETURNS, 0 AS SALESRETURNS FROM Sales WHERE DOCREF='1'GROUP BY GEOCODE
UNION ALL
SELECT GEOCODE, 0 AS NETSALES, SUM(SALES)as FRESHRETURNS, 0 AS SALESRETURNS FROM Sales WHERE DOCREF='2'GROUP BY GEOCODE
UNION ALL
SELECT GEOCODE, 0 AS NETSALES, 0 AS FRESHRETURNS, SUM(SALES)as SALESRETURNS FROM Sales WHERE DOCREF='3'GROUP BY GEOCODE
) AS salesData
GROUP BY GEOCODE