Turn a category into a column in SQL Server - sql

I have a query that gives as result some properties categorizedm but I need every category to be turned into a column
This is my query:
SELECT hist_statusevents.eqmt,
hist_exproot.shiftdate,
hist_statusevents.category,
Sum(hist_statusevents.duration/3600) as Value
FROM Powerview.dbo.hist_eqmtlist hist_eqmtlist,
Powerview.dbo.hist_exproot hist_exproot,
Powerview.dbo.hist_statusevents hist_statusevents
WHERE hist_exproot.shiftindex = hist_statusevents.shiftindex And
hist_statusevents.shiftindex = hist_eqmtlist.shiftindex And
hist_statusevents.eqmt = hist_eqmtlist.eqmtid And
hist_statusevents.eqmt like 'MOTO%'
GROUP BY hist_statusevents.eqmt,
hist_exproot.shiftdate,
hist_statusevents.category
This is the output of the query:
eqmt shiftdate category Value
MOTO705 2011-01-22 00:00:00 5 13,9597222805023
MOTO706 2011-01-28 00:00:00 3 0,280277773737907
MOTO704 2011-02-17 00:00:00 6 8,92749977111816
MOTO705 2011-02-09 00:00:00 6 10,07972240448
MOTO703 2011-03-15 00:00:00 1 22,6561107933521
MOTO704 2011-03-11 00:00:00 5 24
MOTO706 2011-01-27 00:00:00 1 9,95361125469208
MOTO703 2011-03-16 00:00:00 6 3,79916667938232
MOTO704 2011-01-08 00:00:00 6 24
But i need to get the result as this:
eqmt shiftdate 1 2 3 4 5 6 7
MOTO706 2011-01-28 00:00:00 values for each category
MOTO704 2011-02-17 00:00:00
MOTO705 2011-02-09 00:00:00
MOTO703 2011-03-15 00:00:00
i've been trying with select case, but i cant get the structure works

if the category values are fixed and are in the range(1,7) then you can use case based aggregation like below
if the category values are dynamic, you need to use dynamic sql to do pivot
SELECT hist_statusevents.eqmt,
hist_exproot.shiftdate,
sum(case when hist_statusevents.category =1 then (hist_statusevents.duration/3600) else 0 end) as '1',
sum(case when hist_statusevents.category =2 then (hist_statusevents.duration/3600) else 0 end) as '2',
sum(case when hist_statusevents.category =3 then (hist_statusevents.duration/3600) else 0 end) as '3',
sum(case when hist_statusevents.category =4 then (hist_statusevents.duration/3600) else 0 end) as '4',
sum(case when hist_statusevents.category =5 then (hist_statusevents.duration/3600) else 0 end) as '5',
sum(case when hist_statusevents.category =6 then (hist_statusevents.duration/3600) else 0 end) as '6',
sum(case when hist_statusevents.category =7 then (hist_statusevents.duration/3600) else 0 end) as '7'
FROM Powerview.dbo.hist_eqmtlist hist_eqmtlist, Powerview.dbo.hist_exproot hist_exproot, Powerview.dbo.hist_statusevents hist_statusevents
WHERE hist_exproot.shiftindex = hist_statusevents.shiftindex And hist_statusevents.shiftindex = hist_eqmtlist.shiftindex And hist_statusevents.eqmt = hist_eqmtlist.eqmtid And hist_statusevents.eqmt like 'MOTO%'
GROUP BY hist_statusevents.eqmt, hist_exproot.shiftdate

Related

Using SQL, how to calculate count of rows for each ID(column) for each month by using only datetime and put them in monthly columns?

I am relatively new to SQL. I have a dataset as follows:
'ID' 'date'
1 2016-01-01 01:01:06
2 2016-01-02 02:02:07
1 2016-01-03 03:03:08
3 2016-04-04 04:04:09
2 2016-04-05 05:05:00
I want to obtain smth like this:
'ID' 'Count: Jan' 'Count: Feb' 'Count: March' 'Count: April'
1 2 0 0 0
2 1 0 1 0
3 0 0 0 1
I really have no idea how handle this. I could put the data creating a column "month" and another column "count" but I want to be able to have a table like this.
Thanks in advance
You ca use conditional aggregation:
select id,
sum(case when month(date) = 1 then 1 else 0 end) as cnt_jan,
sum(case when month(date) = 2 then 1 else 0 end) as cnt_feb,
. . .
sum(case when month(date) = 12 then 1 else 0 end) as cnt_dec
from t
group by id;

SQL Query to categorize results of separate query

I am trying to run a query on the results of a separate query to update the Route_Type column for each record based on unique Route_Code and Delivery_Day. For each distinct Route_Code from the select query, the Route_Type should be updated based on the following logic:
if there are no records for a specific Route_Code where Delivery_Day = 'Mon' then Route_Type should update to 'A'
if there are no records for a specific Route_Code where Delivery_Day = 'Sat' then Route_Type should update to 'B'
If there are no records for a specific Route_Code where Delivery_Day = 'Mon' OR 'Sat' then Route_Type should be 'TBD'
Else Route_Type = 'Both.'
Data:
Record Route_Code Delivery_Day Route_Type
1 112 Mon
2 112 Thur
3 112 Sat
4 112 Sun
5 113 Tue
6 113 Fri
7 113 Sat
8 113 Sun
9 113 Wed
Select Query:
Select Distinct Route_Code
From Deliveries;
Results:
Route_Code
1 112
2 113
The query should return all unique Route_Code and the calculated Route_Type for each, shown below...
Desired Query Result:
Route_Code Route_Type
1 112 Both
2 113 A
As a follow-up, I want all Route_Codes that have fewer than 1 month of records to display 'TBD.' The logic I have so far is
When
Max(sum(case when Delivery_Day= 'Mon' then 1 else 0 end),
sum(case when Delivery_Day= 'Tue' then 1 else 0 end),
sum(case when Delivery_Day= 'Wed' then 1 else 0 end),
sum(case when Delivery_Day= 'Thu' then 1 else 0 end),
sum(case when Delivery_Day= 'Fri' then 1 else 0 end),
sum(case when Delivery_Day= 'Sat' then 1 else 0 end),
sum(case when Delivery_Day= 'Sun' then 1 else 0 end)
Then 'TBD'
I realize that the native Max() function handles only single arguments, and am wondering where to go from here.
This sounds like aggregation. I find your logic a bit hard to follow. If I understand correctly, "B" has a Monday delivery and "A" has a Saturday. The logic looks like this:
select route_code,
(case when sum(case when Delivery_Day = 'Mon' then 1 else 0 end) > 0 and
sum(case when Delivery_Day = 'Sat' then 1 else 0 end) > 0
then 'Both'
when sum(case when Delivery_Day = 'Mon' then 1 else 0 end) > 0
then 'B'
when sum(case when Delivery_Day = 'Sat' then 1 else 0 end) > 0
then 'A'
else 'TBD'
end) as route_type
from delivies
group by route_code

PostgreSQL transpose rows in to columns

i have one query
select department_id,SUM(quantity) as Quantity,sales_report.date as Date from sales_report where date = '2018-10-04' GROUP BY department_id , Date ORDER BY department_id ASC;
which gives me output like below:
id quantity date
1 204 2018-10-04
2 88 2018-10-04
3 135 2018-10-04
4 72 2018-10-04
5 391 2018-10-04
6 134 2018-10-04
7 386 2018-10-04
8 421 2018-10-04
9 292 2018-10-04
10 86 2018-10-04
11 83 2018-10-04
12 34 2018-10-04
13 3435 2018-10-04
but I need data like this:
id 1 2 3 4 5 6 7 8 9 10 11 12 13
2018-10-04 204 88 135 72 391 134 386 421 292 86 83 34 3435
Can anyone help me to achieve this..
you can try this:
select sales_report.date,
sum(case when id=1 then quantity else 0 end) as '1',
sum(case when id=2 then quantity else 0 end) as '2',
sum(case when id=3 then quantity else 0 end) as '3',
sum(case when id=4 then quantity else 0 end) as '4',
sum(case when id=5 then quantity else 0 end) as '5',
sum(case when id=6 then quantity else 0 end) as '6',
sum(case when id=7 then quantity else 0 end) as '7',
sum(case when id=8 then quantity else 0 end) as '8',
sum(case when id=9 then quantity else 0 end) as '9',
sum(case when id=10 then quantity else 0 end) as '10',
sum(case when id=11 then quantity else 0 end) as '11',
sum(case when id=12 then quantity else 0 end) as '12',
sum(case when id=13 then quantity else 0 end) as '13'
from sales_report where date = '2018-10-04' GROUP BY Date ORDER BY date ASC
you need case when, from your output data set you could do this pivoting
select date, max(case when id=1 then quantity end) as 1_one,
max(case when id=2 then quantity end) as 2_one,
max(case when id=3 then quantity end) as 3_one,
max(case when id=4 then quantity end) as 4_one,
max(case when id=5 then quantity end) as 5_one,
max(case when id=6 then quantity end) as 7_one,
max(case when id=7 then quantity end) as 7_one,
max(case when id=10 then quantity end) as 10_ten from t
group by date

Group by datepart and find total count of individual values of each record

This is table structure;
ID Score Valid CreatedDate
1 A 1 2018-02-19 23:33:10.297
2 C 0 2018-02-19 23:32:40.700
3 B 1 2018-02-19 23:32:30.247
4 A 1 2018-02-19 23:31:37.153
5 B 0 2018-02-19 23:25:08.667
...
I need to find total number of each score and valid in each month
I mean final result should be like
Month A B C D E Valid(1) NotValid(0)
January 123 343 1021 98 12 1287 480
February 516 421 321 441 421 987 672
...
This is what I tried;
SELECT DATEPART(year, CreatedDate) as Ay,
(select count(*) from TableResults where Score='A') as 'A',
(select count(*) from TableResults where Score='B') as 'B',
...
FROM TableResults
group by DATEPART(MONTH, CreatedDate)
but couldn't figure how to calculate all occurrence of scores on each month.
Use conditional aggregation.
SELECT DATEPART(year, CreatedDate) as YR
, DATEPART(month, CreatedDate) MO
, sum(Case when score = 'A' then 1 else 0 end) as A
, sum(Case when score = 'B' then 1 else 0 end) as B
, sum(Case when score = 'C' then 1 else 0 end) as C
, sum(Case when score = 'D' then 1 else 0 end) as D
, sum(Case when score = 'E' then 1 else 0 end) as E
, sum(case when valid = 1 then 1 else 0 end) as Valid
, sum(case when valid = 0 then 1 else 0 end) as NotValid
FROM TableResults
GROUP BY DATEPART(MONTH, CreatedDate), DATEPART(year, CreatedDate)
I'm not a big fan of queries in the select; I find they tend to cause performance problems in the long run. Since we're aggregating here I just applied the conditional logic to all the columns.

How to count sql from one column, and display it in two column

I have a table like this:
idrecord | date
----------------------------------------------
INC-20140308102029 | 2014-03-08 00:00:00.000
INC-20140308102840 | 2014-03-06 00:00:00.000
INC-20140310164404 | 2014-03-10 00:00:00.000
INC-20140311075714 | 2014-03-09 00:00:00.000
NRM-20140310130512 | 2014-04-02 00:00:00.000
NRM-20140311134720 | 2014-03-11 00:00:00.000
USF-20140317212232 | 2014-03-17 00:00:00.000
USF-20140321075402 | 2014-03-18 00:00:00.000
USF-20140321083137 | 2014-03-21 00:00:00.000
how to count this table and display result like this:
month | INC | NRM | USF
march | 4 | 1 | 3
April | 0 | 1 | 0
Thank you
You'd use case to count 1 or zero depending on the string matching or not. Use sum to count.
select
extract(month from thedate) as whichmonth,
sum( case when idrecord like 'INC%' then 1 else 0 end) as inc,
sum( case when idrecord like 'NRM%' then 1 else 0 end) as nrm,
sum( case when idrecord like 'USF%' then 1 else 0 end) as usf
from mytable
group by extract(month from thedate);
The function to extract the month from the date may vary from dbms to dbms. Look the appropriate function up in Google, if extract doesn't work for you.
Don't use the name date for a column. Date is a reserved word in SQL.
Try this
SELECT convert(char(3), date, 0) AS Month,
SUM(Case when LEFT(idrecord,3) = 'INC' then 1 else 0 end) as 'INC',
SUM(Case when LEFT(idrecord,3) = 'NRM' then 1 else 0 end) as 'NRM',
SUM(Case when LEFT(idrecord,3) = 'USF' then 1 else 0 end) as 'USF'
FROM Table1
Group By convert(char(3), date, 0)
Fiddle Demo
or:
SELECT datename(mm, date) AS Month,
SUM(Case when LEFT(idrecord,3) = 'INC' then 1 else 0 end) as 'INC',
SUM(Case when LEFT(idrecord,3) = 'NRM' then 1 else 0 end) as 'NRM',
SUM(Case when LEFT(idrecord,3) = 'USF' then 1 else 0 end) as 'USF'
FROM Table1
Group By datename(mm, date)
Fiddle Demo
Output:
month | INC | NRM | USF
march | 4 | 1 | 3
April | 0 | 1 | 0
try this one
select month (date) as month,
count( case when idrecord like 'INC%' then 1 else 0 end) as inc,
count( case when idrecord like 'NRM%' then 1 else 0 end) as nrm,
count( case when idrecord like 'USF%' then 1 else 0 end) as usf
from table
group by month;