how to create calculated pivot in sql - sql

Scenario
Company XYZ sells products. Company measures their performance by checking how long does it take to complete the entire order. Each order goes through multiple status (Example : Open, Pending, Close)
They count days for each status to know how many days an order was on a particular status. the days are calculated in two different ways, Working Days and Calendar Days
Please refer to the below table:
Question
How to turn this table into a pivot table shown in below picture? also how to add to additional columns which is total of each Working and business day status.
Desired Result:

You can do this:
SELECT *
FROM
(
SELECT
OrderID,
OrderStatus + CountType AS StatusType,
DayCount
FROM CalendarTable
UNION ALL
SELECT
OrderID,
CASE WHEN CountType = 'Working' THEN 'TotalWorking' ELSE 'TotalCalendar' END,
DayCount
FROM CalendarTable
) AS t
PIVOT
(
MAX(DayCount)
For StatusType IN(OpenWorking,
OpenCalendar,
CloseWorking,
CloseCalendar,
PendingWorking,
PendingCalendar,
TotalWorking,
TotalCalendar)
) AS p;
This will give you:
If you don't want to write down all the statuses manually, then you can do ti dynamically:
DECLARE #cols AS NVARCHAR(MAX);
DECLARE #query AS NVARCHAR(MAX);
SELECT #cols = STUFF((SELECT distinct ',' +
QUOTENAME(StatusType)
FROM
(
SELECT
OrderID,
OrderStatus + CountType AS StatusType,
DayCount
FROM CalendarTable
UNION ALL
SELECT
OrderID,
CASE WHEN CountType = 'Working' THEN 'TotalWorking' ELSE 'TotalCalendar' END,
DayCount
FROM CalendarTable
) AS t
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
, 1, 1, '');
SELECT #query = 'SELECT *
FROM
(
SELECT
OrderID,
OrderStatus + CountType AS StatusType,
DayCount
FROM CalendarTable
UNION ALL
SELECT
OrderID,
CASE WHEN CountType = ''Working'' THEN ''TotalWorking'' ELSE ''TotalCalendar'' END,
DayCount
FROM CalendarTable
) AS t
PIVOT
(
MAX(DayCount)
For StatusType IN(' + #cols + ')' +
') p';
execute(#query);
Update:
For column names you can create a new variable #colnames and populate it with the names you want. For the Totals, you can add a WHERE clause to get the total for statuses active and pending only. So your query will be like this:
DECLARE #cols AS NVARCHAR(MAX);
DECLARE #colnames AS NVARCHAR(MAX);
DECLARE #query AS NVARCHAR(MAX);
SELECT #cols = STUFF((SELECT distinct ',' +
QUOTENAME(StatusType)
FROM
(
SELECT
OrderID,
OrderStatus + CountType AS StatusType,
DayCount
FROM CalendarTable
UNION ALL
SELECT
OrderID,
CASE WHEN CountType = 'Working' THEN 'TotalWorking' ELSE 'TotalCalendar' END,
DayCount
FROM CalendarTable
WHERE OrderStatus IN('Active', 'Pending')
) AS t
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
, 1, 1, '');
SELECT #colnames = STUFF((SELECT distinct ',' +
QUOTENAME(StatusType) + ' AS ' + QUOTENAME(StatusTypeName)
FROM
(
SELECT
OrderID,
OrderStatus + CountType AS StatusType,
DayCount,
OrderStatus + CASE WHEN CountType = 'Working' THEN 'WorkDays' ELSE 'CalDays' END AS StatusTypeName
FROM CalendarTable
UNION ALL
SELECT
OrderID,
CASE WHEN CountType = 'Working' THEN 'TotalWorking' ELSE 'TotalCalendar' END,
DayCount,
CASE WHEN CountType = 'Working' THEN 'TotalWorking' ELSE 'TotalCalendar' END
FROM CalendarTable
WHERE OrderStatus IN('Active', 'Pending')
) AS t
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
, 1, 1, '');
SELECT #query = 'SELECT OrderID , ' + #colnames + '
FROM
(
SELECT
OrderID,
OrderStatus + CountType AS StatusType,
DayCount
FROM CalendarTable
UNION ALL
SELECT
OrderID,
CASE WHEN CountType = ''Working'' THEN ''TotalWorking'' ELSE ''TotalCalendar'' END,
DayCount
FROM CalendarTable
WHERE OrderStatus IN(''Active'', ''Pending'')
) AS t
PIVOT
(
SUM(DayCount)
For StatusType IN(' + #cols + ')' +
') p';
execute(#query);
This will give you:
Update
If you want to add a where clause to the manual pivot query, you can do this:
SELECT *
FROM
(
SELECT
OrderID,
OrderStatus + CountType AS StatusType,
DayCount
FROM CalendarTable
WHERE ...
UNION ALL
SELECT
OrderID,
CASE WHEN CountType = 'Working' THEN 'TotalWorking' ELSE 'TotalCalendar' END,
DayCount
FROM CalendarTable
WHERE ...
) AS t
PIVOT
(
MAX(DayCount)
For StatusType IN(OpenWorking,
OpenCalendar,
CloseWorking,
CloseCalendar,
PendingWorking,
PendingCalendar,
TotalWorking,
TotalCalendar)
) AS p;

Related

SQL query to get customers yearly net amount and Year to Year growth percentage

Here is the scenario,
I am creating a report where, for each customer yearly ordered amount will be shown. And than the growth percentage comparing the previous years.
What I have tried so far :
SELECT * FROM (select MrCode MrCode17,MrName MrName17, SUM(NetAmt) NetAmount17,SUM(TotalNetAmt) TotalNetAmount17 from TASKORDER_REGISTER where UCODE = 'SR01'
AND TaskOrder_Dt between '2017-1-1 00:00:00' and '2017-12-31 00:00:00'
GROUP BY MrCode,MrName) as abc
FULL JOIN
(select MrCode MrCode16,MrName MrName16, SUM(NetAmt) NetAmount16,SUM(TotalNetAmt) TotalNetAmount16 from TASKORDER_REGISTER where UCODE = 'SR01'
AND TaskOrder_Dt between '2016-1-1 00:00:00' and '2016-12-31 00:00:00'
GROUP BY MrCode,MrName) AS bbb
ON abc.MrCode17 = bbb.MrCode16
FULL JOIN
(select MrCode MrCode15,MrName MrName15, SUM(NetAmt) NetAmount15,SUM(TotalNetAmt) TotalNetAmount15 from TASKORDER_REGISTER where UCODE = 'SR01'
AND TaskOrder_Dt between '2015-1-1 00:00:00' and '2015-12-31 00:00:00'
GROUP BY MrCode,MrName) AS ccc
ON bbb.MrCode16 = ccc.MrCode15
What is the result :
I am not sure what is the best procedure to accmplish the task. There must sume better queries to get data. And I could not create the growth percentage yet.
Please use following query it will return Year,Difference and [Difference Precantage].
Please add other columns in result set
IF OBJECT_ID('tempdb..#SalesData') IS NOT NULL BEGIN DROP TABLE #SalesData END
IF OBJECT_ID('tempdb..#FinalData') IS NOT NULL BEGIN DROP TABLE #FinalData END
SELECT IDENTITY(int, 1,1) AS ID_Num ,year(TaskOrder_Dt) SalesYear,SUM(NetAmt) TotalAmount
INTO #SalesData
FROM TASKORDER_REGISTER GROUP BY year(TaskOrder_Dt)
SELECT
[current].ID_Num,
[current].TotalAmount,
[current].SalesYear,
[current].TotalAmount - ISNULL([next].TotalAmount, 0) AS Diff,
(([current].TotalAmount - ISNULL([next].TotalAmount,0)) * ISNULL([next].TotalAmount,1)) * 100 AS Diffper
INTO #FinalData
FROM #SalesData AS [current]
LEFT JOIN #SalesData AS [next]
ON [next].ID_Num = (SELECT MAX(ID_Num) FROM #SalesData WHERE ID_Num < [current].ID_Num)
DECLARE #cols AS NVARCHAR(MAX),#query AS NVARCHAR(MAX)
SELECT #cols = STUFF((SELECT ',' + QUOTENAME(SalesYear) FROM #FinalData FOR XML PATH(''), TYPE ).value('.', 'NVARCHAR(MAX)'),1,1,'')
SELECT #query = 'SELECT * FROM (SELECT [SalesYear],Diff,Diffper FROM #FinalData) X
PIVOT (AVG(Diff) for [SalesYear] in (' + #cols + ')) P'
EXEC SP_EXECUTESQL #query

Error during PIVOT in SQL Server 2014

I am trying to create pivot where row is Brand and SKU, sum is qty for column YYMM, but I'm not sure why it is throwing an error. Please help.
Code:
DECLARE #TABLE TABLE
(
SKU VARCHAR(10),
YYMM VARCHAR(50),
BRAND VARCHAR(50),
QTY INT
)
INSERT INTO #TABLE
SELECT '104591168', '2015-January', 'abott', 2 UNION ALL
SELECT '104580709', '2016-January', 'GSK', 2 UNION ALL
SELECT '104720038', '2017-January', 'RANBAXCY', 2 UNION ALL
SELECT '10467011A', '2018-January', 'abott', 2 UNION ALL
SELECT '104590691', '2019-January', 'abott', 10
Pivot code:
select *
from
(select
BRAND, sku, QTY, YYMM
from #TABLE) src
pivot
(sum(QTY)
for [Year Month]
You forgot to finish your query.
Please see the bottom of MSDN article for PIVOT examples.
I would guess that you wanted your query to look something like this:
SELECT *
FROM(
SELECT BRAND, sku, QTY, YYMM
FROM #TABLE
) AS src
PIVOT(
sum(QTY)
for [YYMM] IN( [2015-January], [2016-January], [2017-January] /* add other moneths here */ )
) AS Pivoted
We can make it as Dynamic sql
DECLARE #Column NVARCHAR(max),
#Column2 NVARCHAR(max),
#Sql NVARCHAR(max)
SELECT #Column = Stuff((SELECT DISTINCT ', '
+ Quotename(Cast(yymm AS VARCHAR(20)))
FROM #table
FOR xml path ('')), 1, 1, '')
SELECT #Column2 = Stuff((SELECT DISTINCT ', ' + 'ISNULL('
+ Quotename(Cast(yymm AS VARCHAR(20)))
+ ','
+ '''0''' + ') AS '
+ Quotename(Cast(yymm AS VARCHAR(20)))
FROM #table
FOR xml path ('')), 1, 1, '')
SET #Sql='
SELECT BRAND ,sku,'+#Column2+'
FROM(
SELECT *
FROM #TABLE
) AS src
PIVOT(
sum(QTY)
for [YYMM] IN('+#Column+')
) AS Pivoted
'
PRINT #Sql
EXEC(#Sql)
Result
BRAND sku 2015-January 2016-January 2017-January 2018-January 2019-January
--------------------------------------------------------------------------------------------------------
abott 104590691 0 0 0 0 10
abott 104591168 2 0 0 0 0
abott 10467011A 0 0 0 2 0
GSK 104580709 0 2 0 0 0
RANBAXCY 104720038 0 0 2 0 0

Total sum wrong value in Dynamic Pivot

I have complicated query which works pretty good (MS SQL 2012). But it makes a mistake when sum up same price items. It count them correctly but only takes price once instead of taking them as a count number. It only appears when same item has same price and from same country. Here is my query ;
CREATE TABLE #ITEMS(ID INT,NAME VARCHAR(30))
INSERT INTO #ITEMS
SELECT 1, 'laptop'
UNION ALL
SELECT 2, 'phone'
UNION ALL
SELECT 3, 'playstation'
UNION ALL
SELECT 4, 'MacBook'
CREATE TABLE #Country(ID INT,NAME VARCHAR(30))
INSERT INTO #Country
SELECT 1, 'England'
UNION ALL
SELECT 2, 'Sweden'
UNION ALL
SELECT 3, 'Russia'
UNION ALL
SELECT 4, 'Italy'
CREATE TABLE [#Pre-Request](Id INT, countryId INT, ItemId INT)
INSERT INTO [#Pre-Request]
SELECT 1,1,3
UNION ALL
SELECT 2,2,1
UNION ALL
SELECT 3,2,2
UNION ALL
SELECT 4,3,3
UNION ALL
SELECT 5,3,3
UNION ALL
SELECT 6,2,3
CREATE TABLE #Offers(Id INT, PRICE VARCHAR(50))
INSERT INTO #Offers
SELECT 18,'257$'
UNION ALL
SELECT 19,'151$'
UNION ALL
SELECT 20,'424$'
UNION ALL
SELECT 21,'433$'
UNION ALL
SELECT 22,'151$'
CREATE TABLE #Request(Id INT, preReqId INT, requestStatus INT,winOfferId INT)
INSERT INTO #Request
SELECT 44, 1, 3, 18
UNION ALL
SELECT 11, 2, 4, 21
UNION ALL
SELECT 53, 3, 4, 20
UNION ALL
SELECT 87, 4, 3, 22
UNION ALL
SELECT 43, 5, 3, 19
UNION ALL
SELECT 43, 6, 2, Null
;WITH CTE AS
(
SELECT DISTINCT I.NAME ITEMNAME,C.NAME COUNTRYNAME
,CAST(REPLACE(TAB.PRICE,'$','')AS INT)PRICE
,COUNT(CASE WHEN TAB.PRICE IS NOT NULL THEN I.NAME END) OVER(PARTITION BY C.NAME,I.NAME) CNTITEM
FROM [#Pre-Request] PR
LEFT JOIN #Items I ON PR.ITEMID=I.ID
LEFT JOIN #COUNTRY C ON PR.COUNTRYID = C.ID
OUTER APPLY
(
SELECT R.preReqId,R.winOfferId,O.PRICE
FROM #Request R
JOIN #Offers O ON R.winOfferId=O.Id
WHERE PR.ID=R.preReqId
)TAB
UNION
-- Used to select Item name and country that are not in Pre-request table and other tables
SELECT I.NAME ,C.NAME ,NULL,0
FROM #Items I
CROSS JOIN #COUNTRY C
)
,CTE2 AS
(
-- Find the sum for number of items
SELECT DISTINCT ISNULL(ITEMNAME,'TOTAL')ITEMNAME,ISNULL(COUNTRYNAME,'TOTAL')COUNTRYNAME,
SUM(PRICE)PRICE
FROM CTE
GROUP BY ITEMNAME,COUNTRYNAME
WITH CUBE
)
,CTE3 AS
(
-- Find the sum of PRICE
SELECT DISTINCT ISNULL(ITEMNAME,'TOTAL')ITEMNAME,ISNULL(COUNTRYNAME,'TOTAL')COUNTRYNAME--,CNTITEM
,SUM(CNTITEM)CNTITEM
FROM
(
SELECT DISTINCT ITEMNAME,COUNTRYNAME,CNTITEM
FROM CTE
)TAB
GROUP BY ITEMNAME,COUNTRYNAME
WITH CUBE
)
SELECT C2.*,C3.CNTITEM,
CAST(C3.CNTITEM AS VARCHAR(20))+'x'+' ' + CAST(C2.PRICE AS VARCHAR(20))+'$' NEWCOL
INTO #NEWTABLE
FROM CTE2 C2
JOIN CTE3 C3 ON C2.COUNTRYNAME=C3.COUNTRYNAME AND C2.ITEMNAME=C3.ITEMNAME
DECLARE #cols NVARCHAR (MAX)
SELECT #cols = COALESCE (#cols + ',[' + ITEMNAME + ']', '[' + ITEMNAME + ']')
FROM (SELECT DISTINCT ITEMNAME FROM #NEWTABLE WHERE ITEMNAME<>'TOTAL') PV
ORDER BY ITEMNAME
-- Since we need Total in last column, we append it at last
SELECT #cols += ',[Total]'
DECLARE #query NVARCHAR(MAX)
SET #query = 'SELECT COUNTRYNAME,' + #cols + ' FROM
(
SELECT DISTINCT ITEMNAME,COUNTRYNAME,ISNULL(NEWCOL,''0x 0$'')NEWCOL
FROM #NEWTABLE
) x
PIVOT
(
MIN(NEWCOL)
FOR ITEMNAME IN (' + #cols + ')
) p
ORDER BY CASE WHEN (COUNTRYNAME=''Total'') THEN 1 ELSE 0 END,COUNTRYNAME'
EXEC SP_EXECUTESQL #query
and here is result ;
As you can see there are 2 "playstation" from "Russia" it takes correct count (2x) but only take 1 price "151$" (normally it must be 302$). How can I fix this without making major changes from query? Thank you.
I think this does what you want. The problem is in your first CTE where you do the item count and get a distinct on the ItemName, CountryName, and Price.
Instead of getting a distinct, do a group by as shown below and SUM the price.
SELECT I.NAME ITEMNAME, C.NAME COUNTRYNAME
,SUM(CAST(REPLACE(TAB.PRICE,'$','')AS INT))PRICE
,COUNT(CASE WHEN TAB.PRICE IS NOT NULL THEN 1 ELSE NULL END) CNTITEM
FROM [#Pre-Request] PR
LEFT JOIN #Items I ON PR.ITEMID=I.ID
LEFT JOIN #COUNTRY C ON PR.COUNTRYID = C.ID
OUTER APPLY
(
SELECT R.preReqId,R.winOfferId,O.PRICE
FROM #Request R
JOIN #Offers O ON R.winOfferId=O.Id
WHERE PR.ID=R.preReqId
)TAB
GROUP BY
I.NAME
,C.NAME
EDIT:
Here are the results I get:
Here's all of your code starting from the CTEs:
;WITH CTE AS
(
SELECT I.NAME ITEMNAME, C.NAME COUNTRYNAME
,SUM(CAST(REPLACE(TAB.PRICE,'$','')AS INT))PRICE
,COUNT(CASE WHEN TAB.PRICE IS NOT NULL THEN 1 ELSE NULL END) CNTITEM
FROM [#Pre-Request] PR
LEFT JOIN #Items I ON PR.ITEMID=I.ID
LEFT JOIN #COUNTRY C ON PR.COUNTRYID = C.ID
OUTER APPLY
(
SELECT R.preReqId,R.winOfferId,O.PRICE
FROM #Request R
JOIN #Offers O ON R.winOfferId=O.Id
WHERE PR.ID=R.preReqId
)TAB
GROUP BY
I.NAME
,C.NAME
UNION
-- Used to select Item name and country that are not in Pre-request table and other tables
SELECT I.NAME ,C.NAME ,NULL,0
FROM #Items I
CROSS JOIN #COUNTRY C
)
,CTE2 AS
(
-- Find the sum for number of items
SELECT DISTINCT ISNULL(ITEMNAME,'TOTAL')ITEMNAME,ISNULL(COUNTRYNAME,'TOTAL')COUNTRYNAME,
SUM(PRICE)PRICE
FROM CTE
GROUP BY ITEMNAME,COUNTRYNAME
WITH CUBE
)
,CTE3 AS
(
-- Find the sum of PRICE
SELECT DISTINCT ISNULL(ITEMNAME,'TOTAL')ITEMNAME,ISNULL(COUNTRYNAME,'TOTAL')COUNTRYNAME--,CNTITEM
,SUM(CNTITEM)CNTITEM
FROM
(
SELECT DISTINCT ITEMNAME,COUNTRYNAME,CNTITEM
FROM CTE
)TAB
GROUP BY ITEMNAME,COUNTRYNAME
WITH CUBE
)
SELECT C2.*,C3.CNTITEM,
CAST(C3.CNTITEM AS VARCHAR(20))+'x'+' ' + CAST(C2.PRICE AS VARCHAR(20))+'$' NEWCOL
INTO #NEWTABLE
FROM CTE2 C2
JOIN CTE3 C3 ON C2.COUNTRYNAME=C3.COUNTRYNAME AND C2.ITEMNAME=C3.ITEMNAME
DECLARE #cols NVARCHAR (MAX)
SELECT #cols = COALESCE (#cols + ',[' + ITEMNAME + ']', '[' + ITEMNAME + ']')
FROM (SELECT DISTINCT ITEMNAME FROM #NEWTABLE WHERE ITEMNAME<>'TOTAL') PV
ORDER BY ITEMNAME
-- Since we need Total in last column, we append it at last
SELECT #cols += ',[Total]'
DECLARE #query NVARCHAR(MAX)
SET #query = 'SELECT COUNTRYNAME,' + #cols + ' FROM
(
SELECT DISTINCT ITEMNAME,COUNTRYNAME,ISNULL(NEWCOL,''0x 0$'')NEWCOL
FROM #NEWTABLE
) x
PIVOT
(
MIN(NEWCOL)
FOR ITEMNAME IN (' + #cols + ')
) p
ORDER BY CASE WHEN (COUNTRYNAME=''Total'') THEN 1 ELSE 0 END,COUNTRYNAME'
EXEC SP_EXECUTESQL #query

Dynamic pivot query in sql server

I have a functioning pivot query for static column values which i want to convert for dynamic column values.
The query is :
with a as (
select request_id, dateadd(month,datediff(month,0,logged_datetime),0) as 'Month'
,dateadd(month,datediff(month,0,logged_datetime),0) as 'Year'
from requests
)
select * from (
select datepart(m,a.Month) as 'months',datepart(YEAR,a.Year) as 'years',a.request_id
from a ) ps
pivot (
count(request_id) for [years] in ([2008],[2009],[2010],[2011],[2012],[2013],[2014],[2015])
) as pvt
order by months
For the dynamic query written below I am getting errors like
Msg 207, Level 16, State 1, Line 5 Invalid column name '2010'. :
select distinct datepart(year,dateadd(month,datediff(month,0,logged_datetime),0)) as 'Yearz'
into #t
FROM requests
DECLARE #Dynamic AS NVARCHAR(MAX)
DECLARE #ColumnName AS NVARCHAR(MAX)
SELECT #ColumnName= ISNULL(#ColumnName + ',','')
+ QUOTENAME(Yearz)
FROM (SELECT * from #t) AS Yea
SET #Dynamic =
N'
select * from (
select datepart(m,dateadd(month,datediff(month,0,logged_datetime),0)) as months,' + #ColumnName + ',request_id
from requests ) ps
pivot (
count(request_id) for [Years] in (' + #ColumnName + ')
) as pvt
order by months
'
EXEC sp_executesql #Dynamic
SAMPLE TABLE
SELECT * INTO #REQUESTS
FROM
(
SELECT 1 request_id, '2012-06-01' logged_datetime
UNION ALL
SELECT 2 request_id, '2012-05-01'
UNION ALL
SELECT 11 request_id, '2012-06-01'
UNION ALL
SELECT 12 request_id, '2012-05-01'
UNION ALL
SELECT 3 request_id, '2012-07-01'
UNION ALL
SELECT 4 request_id, '2013-09-01'
UNION ALL
SELECT 5 request_id, '2013-10-01'
UNION ALL
SELECT 6 request_id, '2014-01-01'
UNION ALL
SELECT 7 request_id, '2014-02-01'
UNION ALL
SELECT 8 request_id, '2014-03-01'
UNION ALL
SELECT 9 request_id, '2014-05-01'
UNION ALL
SELECT 10 request_id, '2015-11-01'
)TAB
QUERY
Get the column for years and order it in numeric order
DECLARE #cols NVARCHAR (MAX)
SELECT #cols = COALESCE (#cols + ',[' + CAST([YEAR] AS VARCHAR(4)) + ']', '[' + CAST([YEAR] AS VARCHAR(4)) + ']')
FROM (SELECT DISTINCT YEAR(dateadd(month,datediff(month,0,logged_datetime),0)) [YEAR] FROM #REQUESTS) PV
ORDER BY CAST([YEAR] AS INT)
Now pivot the query
DECLARE #query NVARCHAR(MAX)
SET #query = 'SELECT * FROM
(
-- We will get the count for a year and number of request_id in that month here as CNT column
select DISTINCT datepart(m,a.Month) as ''months'',datepart(YEAR,a.Year) as ''years'',
COUNT(*) OVER(PARTITION BY datepart(YEAR,a.Year),datepart(m,a.Month)) CNT
from
(
select request_id, dateadd(month,datediff(month,0,logged_datetime),0) as ''Month''
,dateadd(month,datediff(month,0,logged_datetime),0) as ''Year''
from #requests
)a
) x
PIVOT
(
MIN(CNT)
FOR years IN (' + #cols + ')
) p
ORDER BY MONTHS;'
EXEC SP_EXECUTESQL #query
Click here to view the result
I think you need to wrap your dynamic column names using the QUOTENAME function:
See example here:

How to add two select queries

Can the below sql query be possible.
I want to have three counts from the same table in different columns with one query only.
select COUNT(Status) as attendedcount from Ebrahim_30359715 where Status='Attended'
UNION
select COUNT(Status) as notallocatedcount from Ebrahim_30359715 where Status='Not Allocated'
UNION
select COUNT(Status) as allocatedbutnotcount from Ebrahim_30359715 where Status='Allocated But Not Attended'
Better use
select SUM(case when Status='Attended' then 1 end) as attendedcount,
SUM(case when Status='Not Attended' then 1 end) as notallocatedcount,
SUM(case when Status='Allocated But Not Attended' then 1 end) as allocatedbutnotcount
from Ebrahim_30359715
With union you would have to either make 3 different columns or add an extra column indicating which value you store in column1.
Try this one. This will work for new status too. you don't have to explicitly mention the status
DECLARE #cols AS VARCHAR(max),
#sql AS NVARCHAR(max)
SELECT #cols = Stuff((SELECT ',' + Quotename(status)
FROM Ebrahim_30359715
GROUP BY status
FOR xml path(''), type).value('.', 'VARCHAR(MAX)'), 1, 1,'')
SET #sql = 'select * from
(select count(1) as cnt ,status
from Ebrahim_30359715
group by status )
src pivot (max(cnt) for status in (' + #cols + ')) piv'
EXEC Sp_executesql
#sql