How to display 0 in all the columns in a table when sum returned for all the columns is 0? - sql

Currently I am getting Blank columns But I want 0 Here as shown in the image. Click here for the Image. Below is my query and I want all the columns to display 0 when sum returned is 0.
SELECT COUNT(*) AS Inserted,
SUM(CASE WHEN status = 0 THEN 1 ELSE 0 END) AS Pending,
SUM(CASE WHEN status = 1 THEN 1 ELSE 0 END) AS Completed,
SUM(CASE WHEN status = 2 THEN 1 ELSE 0 END) AS Failure
FROM [dbo].[ETIME_TIMECARD]
where cast(CreateDateTime as date) = CAST(GETDATE() AS DATE)
Group By cast(CreateDateTime as date)

You're getting no results because your WHERE isn't returning any results and you have a GROUP BY with nothing to group on. In truth, the GROUP BY appears to not be required.
SELECT COUNT(*) AS Inserted,
ISNULL(SUM(CASE WHEN status = 0 THEN 1 ELSE 0 END),0) AS Pending,
ISNULL(SUM(CASE WHEN status = 1 THEN 1 ELSE 0 END),0) AS Completed,
ISNULL(SUM(CASE WHEN status = 2 THEN 1 ELSE 0 END),0) AS Failure
FROM [dbo].[ETIME_TIMECARD]
WHERE CreateDateTime >= CAST(GETDATE() AS date)
AND CreateDateTime < CAST(DATEADD(DAY, 1, GETDATE()) AS date);
Though, personally, I would switch to a COUNT as you clearly are counting, and then you don't need to ISNULL, as a COUNT will not return NULL:
SELECT COUNT(*) AS Inserted,
COUNT(CASE status WHEN 0 THEN 1 END) AS Pending,
COUNT(CASE status WHEN 1 THEN 1 END) AS Completed,
COUNT(CASE status WHEN 2 THEN 1 END) AS Failure
FROM [dbo].[ETIME_TIMECARD]
WHERE CreateDateTime >= CAST(GETDATE() AS date)
AND CreateDateTime < CAST(DATEADD(DAY, 1, GETDATE()) AS date);

Related

SQL two decimal

How to make persen_sukses or persen_gagal only get 2 decimal ?
I try use round but get some error.
May be anyone can help me.
Here is my sql
SELECT * ,(CASE WHEN all_trx.trx_gagal = 0 THEN 100 WHEN all_trx.trx_sukses = 0 THEN 0 ELSE (CAST(all_trx.trx_sukses AS float)/CAST(all_trx.trx_total AS float)*100) END) AS persen_sukses,
(CASE WHEN all_trx.trx_sukses = 0 THEN 100 WHEN all_trx.trx_gagal = 0 THEN 0 ELSE (CAST(all_trx.trx_gagal AS float)/CAST(all_trx.trx_total AS float)*100) END) AS persen_gagal
FROM
(SELECT kode_produk AS Produk,
COUNT(CASE WHEN status = '20' THEN 1 END) AS trx_sukses,
COUNT(CASE WHEN status > '20' THEN 1 END) AS trx_gagal,
COUNT(CASE WHEN status >= '20' THEN 1 END) AS trx_total
FROM transaksi WHERE CAST(tgl_entri AS DATE) = CAST(GETDATE() AS DATE) GROUP BY kode_produk)
AS all_trx
SELECT *
,(CASE
WHEN all_trx.trx_gagal = 0 THEN 100
WHEN all_trx.trx_sukses = 0 THEN 0
--ELSE (CAST(all_trx.trx_sukses AS float)/CAST(all_trx.trx_total AS float)*100)
ELSE CAST(all_trx.trx_sukses*100.0 / all_trx.trx_total as numeric(18,2) )
END) AS persen_sukses
,(CASE
WHEN all_trx.trx_sukses = 0 THEN 100
WHEN all_trx.trx_gagal = 0 THEN 0
--ELSE (CAST(all_trx.trx_gagal AS float)/CAST(all_trx.trx_total AS float)*100)
ELSE CAST(all_trx.trx_gagal*100.0 / all_trx.trx_total as numeric(18,2) )
END) AS persen_gagal
FROM
(
SELECT
kode_produk AS Produk,
COUNT(CASE WHEN status = '20' THEN 1 END) AS trx_sukses,
COUNT(CASE WHEN status > '20' THEN 1 END) AS trx_gagal,
COUNT(CASE WHEN status >= '20' THEN 1 END) AS trx_total
FROM transaksi
WHERE CAST(tgl_entri AS DATE) = CAST(GETDATE() AS DATE)
GROUP BY kode_produk
) AS all_trx
Dear i am able to fix the issue in your query, Pleae note the only change i did is ELSE part of Case Statement. I executed the query and now returning the value upto two decimal places only. If you have to increase or decrease the digits after the decimal sign update the value of numeric(18,2) here 2 is number of digit after decimal.

Get data of 2 different dates in 2 different columns sql

I have a sql table having columns Name, VisitingDate, StayTime
I want a query which can give me data in which in 1 column I can get data of thismonthvisit and other column I can get data of lastmonthvisit and in 3rd column I can data of summation of StayTime of particular person .
Database Table : --
Name
VisitingDate
StayTime(in minutes)
A
2021-04-20
5
A
2021-04-21
15
A
2021-03-20
10
B
2021-03-20
5
Result Wanted : --
Name
Thismonthvisit
TotalStayTimeThismonth(in minutes)
LastmonthVisit
TotalStayTimelastmonth(in minutes)
A
2
20
1
10
B
0
0
1
5
Here is what you are looking for :
select name,
SUM(CASE WHEN FORMAT(VisitingDate, 'YYYYMM') = FORMAT(getdate(),'YYYYMM') THEN 1 ELSE 0 END) AS ThisMonthVisit,
SUM(CASE WHEN FORMAT(VisitingDate, 'YYYYMM') = FORMAT(getdate(),'YYYYMM') THEN StayTime ELSE 0 END) AS TotalStayTimeThisMonth,
SUM(CASE WHEN FORMAT(VisitingDate, 'YYYYMM') = FORMAT(dateadd(month, -1, getdate()),'YYYYMM') THEN 1 ELSE 0 END) AS LastMonthVisit,
SUM(CASE WHEN FORMAT(VisitingDate, 'YYYYMM') = FORMAT(dateadd(month, -1, getdate()),'YYYYMM') THEN StayTime ELSE 0 END) AS TotalStayTimeLastMonth
from MyTable
where FORMAT(VisitingDate, 'YYYYMM') > FORMAT(dateadd(month, -2, getdate()),'YYYYMM')
group by Name
SEE DEMO HERE
You can use aggregation:
select name,
sum(case when month(visitingdate) = month(getdate())
then 1 else 0
end) as cnt_thismonth,
sum(case when month(visitingdate) = month(getdate())
then staytime else 0
end) staytime_thismonth,
sum(case when month(visitingdate) <> month(getdate())
then 1 else 0
end) as cnt_lastmonth,
sum(case when month(visitingdate) <> month(getdate())
then staytime else 0
end) staytime_lastmonth
from t
where visitingdate >= dateadd(month, -1, datefromparts(year(getdate()), month(getdate()), 1))
group by name;

SQL row in column

I have this SQL query
SELECT COUNT(*)*100/(SELECT COUNT(*) FROM tickets WHERE status = 'closed')
FROM tickets
WHERE closed_at <= due_at
UNION
SELECT COUNT(*)*100/(SELECT COUNT(*) FROM tickets WHERE status = 'closed')
FROM tickets
WHERE closed_at > due_at;
and it returns this
ROW 1 - 35
ROW 2 - 47
but I need the return like this:
1 | 2 |
35 47
I need the returns in columns, not rows.
Thanks.
Use conditional aggregation. I would recommend:
SELECT (SUM(CASE WHEN closed_at <= due_at THEN 100.0 ELSE 0 END) /
SUM(CASE WHEN status = 'closed' THEN 1 ELSE 0 END)
),
(SUM(CASE WHEN closed_at > due_at THEN 100.0 ELSE 0 END) /
SUM(CASE WHEN status = 'closed' THEN 1 ELSE 0 END)
)
FROM tickets ;
It seems strange that you are filtering on status = 'closed' in the denominator, but not in the numerator. If status = closed should be the filter for both, then you can simplify this to:
SELECT AVG(CASE WHEN closed_at <= due_at THEN 100.0 ELSE 0 END),
AVG(CASE WHEN closed_at > due_at THEN 100.0 ELSE 0 END)
FROM tickets
WHERE status = 'closed';

tsql query efficiency

I have a table that is defined as follows:
CREATE TABLE [dbo].[ListingStats](
[ListingStatID] [int] IDENTITY(1,1) NOT NULL,
[StatTypeID] [int] NOT NULL,
[CreatedDate] [date] NOT NULL,
[ListingID] [int] NOT NULL,
CONSTRAINT [PK_ListingStats] PRIMARY KEY CLUSTERED
(
[ListingStatID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF,
ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
I am trying to get 4 totals for each type (listingStatTypeID) for today, last 7 days, last 30 days, and all time.
I am not really sure what the most efficient query will be. Right now I have the following that I can repeat for each TYPE but that will be a big query and it will be a lot of calls.
declare #listingID int
set #listingID = 209722
--today
select count(1) from ListingStats where listingid = #listingid and CreatedDate = getdate()
--last 7 days
select count(1) from ListingStats where listingid = #listingid and CreatedDate > getdate()-7
--last 30 days
select count(1) from ListingStats where listingid = #listingid and CreatedDate > getdate()-30
--all time
select count(1) from ListingStats where listingid = #listingid
I am always calling this for one listing at a time by providing a listingID.
If anyone could provide a direction I would appreciate it. Should I create a view of some sort?
Expected Results
-Type------Today-----7Days---30Days---Ever
1 44 50 500 5000
2 22 40 90 1000
3 55 55 555 5555
For a single listing, you can use CASE expressions to get the four values in a single query:
SELECT SUM(CASE WHEN CreatedDate = getdate() THEN 1 ELSE 0 END) AS v_today,
SUM(CASE WHEN CreatedDate > getdate()-7 THEN 1 ELSE 0 END) AS v_week,
SUM(CASE WHEN CreatedDate > getdate()-30 THEN 1 ELSE 0 END) AS v_month,
COUNT(*) AS v_alltime
FROM ListingStats
WHERE listingid = #listingid
For all listing IDs, then
SELECT ListingID,
SUM(CASE WHEN CreatedDate = getdate() THEN 1 ELSE 0 END) AS v_today,
SUM(CASE WHEN CreatedDate > getdate()-7 THEN 1 ELSE 0 END) AS v_week,
SUM(CASE WHEN CreatedDate > getdate()-30 THEN 1 ELSE 0 END) AS v_month,
COUNT(*) AS v_alltime
FROM ListingStats
GROUP BY ListingID
If you want to get summaries for each StatTypeID (within a ListingID), then:
SELECT ListingID,
StatTypeID,
SUM(CASE WHEN CreatedDate = getdate() THEN 1 ELSE 0 END) AS v_today,
SUM(CASE WHEN CreatedDate > getdate()-7 THEN 1 ELSE 0 END) AS v_week,
SUM(CASE WHEN CreatedDate > getdate()-30 THEN 1 ELSE 0 END) AS v_month,
COUNT(*) AS v_alltime
FROM ListingStats
GROUP BY ListingID, StatTypeID
If you want the summaries by StatTypeID across all ListingIDs, then:
SELECT StatTypeID,
SUM(CASE WHEN CreatedDate = getdate() THEN 1 ELSE 0 END) AS v_today,
SUM(CASE WHEN CreatedDate > getdate()-7 THEN 1 ELSE 0 END) AS v_week,
SUM(CASE WHEN CreatedDate > getdate()-30 THEN 1 ELSE 0 END) AS v_month,
COUNT(*) AS v_alltime
FROM ListingStats
GROUP BY StatTypeID
Judging from the 'expected results' section that has been added, this last query is closest to what you need. And judging from the comments, if you want the summaries by StatTypeID for a specific ListingID, then:
SELECT StatTypeID,
SUM(CASE WHEN CreatedDate = getdate() THEN 1 ELSE 0 END) AS v_today,
SUM(CASE WHEN CreatedDate > getdate()-7 THEN 1 ELSE 0 END) AS v_week,
SUM(CASE WHEN CreatedDate > getdate()-30 THEN 1 ELSE 0 END) AS v_month,
COUNT(*) AS v_alltime
FROM ListingStats
WHERE ListingID = #listingid
GROUP BY StatTypeID
If there are issues with your getdate() function calls (as suggested by Gordon Linoff in his answer), you also need to fix those.
You can do this with conditional aggregation. This puts the values into four columns:
select sum(case when CreatedDate = cast(getdate() as date) then 1 else 0 end) as today,
sum(case when CreatedDate > cast(getdate() - 7 as date) then 1 else 0 end) as lastweek,
sum(case when CreatedDate > cast(getdate() - 30 as date) then 1 else 0 end) as last30,
count(*) as ever
from ListingStats
where listingid = #listingid;
Note that getdate() returns a datetime, with a time component (despite the name), so this query casts the value to a date (removing the time component).
To get this for all listing ids:
select sum(case when CreatedDate = cast(getdate() as date) then 1 else 0 end) as today,
sum(case when CreatedDate > cast(getdate() - 7 as date) then 1 else 0 end) as lastweek,
sum(case when CreatedDate > cast(getdate() - 30 as date) then 1 else 0 end) as last30,
count(*) as ever
from ListingStats
group by listingid;

Group by year in sql

I am trying to group by year but was not able to do.I can get the column count but not year wise. this is what i tried.
select t_contract ,
sum(CASE t_contract when '18' then 1 else 0 end) as XL,
sum(CASE t_contract when '01' then 1 else 0 end) as VC,
sum(CASE t_contract when '75' then 1 else 0 end) as AN,
sum(CASE t_contract when '48' then 1 else 0 end) as CS
from icps.dbo.tickets
WHERE
t_date_time_issued >= DATEADD(year, -6, GETDATE())
GROUP BY contract
.. but i want to add year .. where i have t_date_time _issued column.
My another query is I have a column called t_zone_name and I want to sum all the rows where t_zone_anme like '%ICeland%' an i tried this:
sum(CASE t_zone_name like '%ICeland%' then 1 else 0 end) as ICELAND
but I get an error on statement like... thanks in advance.
LIKE
YEAR XL VC AN CS total
2010 50 50 50 50 200
2011 5 5 5 5 20
Try the below query:
SELECT t_contract, YEAR(t_date_time_issued) As Yr, SUM(CASE WHEN t_zone_name like '%ICeland%' THEN 1 ELSE 0 END) AS ICELAND
SUM(CASE t_contract when '18' then 1 else 0 end) as XL,
SUM(CASE t_contract when '01' then 1 else 0 end) as VC,
SUM(CASE t_contract when '75' then 1 else 0 end) as AN,
SUM(CASE t_contract when '48' then 1 else 0 end) as CS
FROM icps.dbo.tickets
WHERE YEAR(t_date_time_issued) >= (YEAR(GetDate()) - 6)
GROUP BY t_contract, YEAR(t_date_time_issued)
You might need change the order of t_contract and YEAR(t_date_time_issued) depending on which grouping you want to apply first.
As suggested by #ray I have replaced DATEPART(yyyy, t_date_time_issued) >= DATEPART(yyyy, DATEADD(year, -6, GETDATE())) with year(t_date_time_issued) >= (year(GetDate()) - 6)
If you want to group by year, in sql server, you might
GROUP BY DATEDIFF(year,t_date_time_issued, GETDATE())
In other DB engine, usually has method to get year part, or use substring to get year part from a time string.