2 Conditions for the same column in a SQl query - sql

How can i get the distinct dates in a table where R.TypeofDayID = 2 and it should not include dates with R.TypeofDayID = 1
I can get all the distinct dates for R.TypeofDayID = 2 using the below query but i am not sure how i can add a condition to get dates where TypeofDayID = 2 and the date should not have TypeofDayID = 1 in any row.
Select count(distinct(R.Date)) from RepInfo R
where R.TypeofDayID = 2 and Month(R.Date) = 2 and Year(R.Date) = 2013
I hope i am clear. This is in SQL Server 2005. Thank you in advance!

Select R.Date, count(*) as cnt
from RepInfo R
where Month(R.Date) = 2 and Year(R.Date) = 2013
group by R.Date
having sum(case when TypeofDayID <> 2 then 1 else 0 end) = 0

Why are you using a COUNT() function in your select statement if you want the the output to be a list of distinct dates? Would you get your desired result from changing your select to something like this:
Select distinct(R.Date)

Related

I just started learning SQL and I couldn't do the query, can you help me?

There is a field in the sql query that I can't do. First of all, a new column must be added to the table below. The value of this column needs to be percent complete, so it's a percentage value. So for example, there are 7 values from Cupboard=1 shelves. Where IsCounted is here, 3 of them are counted. In other words, those with Cupboard = 1 should write the percentage value of 3/7 as the value in the new column to be created. If the IsCounted of the others is 0, it will write zero percent. How can I do this?
My Sql Code:
SELECT a.RegionName,
a.Cupboard,
a.Shelf,
(CASE WHEN ToplamSayım > 0 THEN 1 ELSE 0 END) AS IsCounted
FROM (SELECT p.RegionName,
r.Shelf,
r.Cupboard,
(SELECT COUNT(*)
FROM FAZIKI.dbo.PM_ProductCountingNew
WHERE RegionCupboardShelfTypeId = r.Id) AS ToplamSayım
FROM FAZIKI.dbo.DF_PMRegionType p
JOIN FAZIKI.dbo.DF_PMRegionCupboardShelfType r ON p.Id = r.RegionTypeId
WHERE p.WarehouseId = 45) a
ORDER BY a.RegionName;
The result is as in the picture below:
It looks like a windowed AVG should do the trick, although it's not entirely clear what the partitioning column should be.
The SELECT COUNT can be simplified to an EXISTS
SELECT a.RegionName,
a.Cupboard,
a.Shelf,
a.IsCounted,
AVG(a.IsCounted * 1.0) OVER (PARTITION BY a.RegionName, a.Cupboard) Percentage
FROM (
SELECT p.RegionName,
r.Shelf,
r.Cupboard,
CASE WHEN EXISTS (SELECT 1
FROM FAZIKI.dbo.PM_ProductCountingNew pcn
WHERE pcn.RegionCupboardShelfTypeId = r.Id
) THEN 1 ELSE 0 END AS IsCounted
FROM FAZIKI.dbo.DF_PMRegionType p
JOIN FAZIKI.dbo.DF_PMRegionCupboardShelfType r ON p.Id = r.RegionTypeId
WHERE p.WarehouseId = 45
) a
ORDER BY a.RegionName;

Conditional for a field generated by a SELECT statement

SELECT
Req_PK,
Req_PostDate,
Req_code,
Req_CreateDate,
Req_FillDate,
Req_Canceldate,
Req_Hold,
(
Select Convert(varchar(50),Count(CanReq_PK))
From CanReq
Where CanReq_ReqFK = Req_PK) AS Applications,
Req_PublishstatusFK
FROM Req
WHERE Req_Filled <> 1
AND Req_Cancelled <> 1
AND Req_Template <> 1
AND Req_PublishstatusFK = 1
AND Req_publishstatusfk = 1
How do I modify this query so the Applications field/alias is not the everything returned by the SELECT statement but everything except the ones with value '0'?
Help is very much appreciated!
Use an explicit JOIN instead:
SELECT r.Req_PK, r.Req_PostDate, r.Req_code, r.Req_CreateDate, r.Req_FillDate,
r.Req_Canceldate, r.Req_Hold,
cr.num_Applications,
r.Req_PublishstatusFK
FROM Req r JOIN
(SELECT cr.CanReq_ReqFK, Count(*) as num_applications
FROM CanReq cr
GROUP BY cr.CanReq_ReqFK
) cr
ON cr.CanReq_ReqFK = r.Req_PK
WHERE r.Req_Filled <> 1 AND r.Req_Cancelled <> 1 AND r.Req_Template <> 1 AND
r.Req_PublishstatusFK = 1 AND r.Req_publishstatusfk = 1;
This will filter out any rows that don't have a record in CanReq -- the ones that would have a count of 0 in your version of the query.
I don't know why you would want the count to be a string. Of course, you can include the conversion if you need it, but it doesn't seem necessary to me.

SQL: Get dates with two specific events

Table:
Logs
Fields:
LogDate datetime,
ErrId int
ErrId 9 and 5 sometimes occur on same date.
How can I find those dates?
Of course the task can be about any pair of ErrIds not just 9 and 5.
I ended up with following sql statement:
select distinct l_1.LogDate
from logs l_1
where exists (select * from logs l_2 where l_1.LogDate = l_2.LogDate and l_2.ErrId = 9)
and exists (select * from logs l_3 where l_1.LogDate = l_3.LogDate and l_3.ErrId = 5)
The question: is there better solution for the task?
You could use a self-join like this:
select distinct l_1.LogDate
from logs l_1
inner join logs l_2 on l_1.LogDate = l_2.LogDate
where l_1.ErrId = 9
and l_2.ErrId = 5
Note that generally it is better to use group by instead of distinct. Give it a try:
select l_1.LogDate
from logs l_1
inner join logs l_2 on l_1.LogDate = l_2.LogDate
where l_1.ErrId = 9
and l_2.ErrId = 5
group by l_1.LogDate
Perhaps the easiest method is simply group by with having:
select l.LogDate
from logs l
group by l.log_date
having sum(case when l.ErrId = 9 then 1 else 0 end) > 0 and
sum(case when l.ErrId = 5 then 1 else 0 end) > 0;
If you are only looking for a fixed set of values, you can also write this as:
select l.LogDate
from logs l
where l.ErrId in (5, 9)
group by l.log_date
having count(distinct l.ErrId) = 2;
Both of these should be faster than doing a group by/distinct along with a join.

SQLite3: Return a NULL if no records exist in SUM()

I would like to SUM() while also using a WHERE but when there are no records found for a certain ID I would like it to return NULL instead of just not returning anything.
Initial Code:
SELECT
ID,
SUM(CASE WHEN EVENTS = 3 THEN 1 ELSE 0 END)
FROM Events_ID
WHERE
YEAR = 2012
GROUP BY ID
This would not return an ID if there were no events for it in 2012.
I then changed it to the following that appears to work but is around 100x slower!
SELECT
ID,
(SELECT
SUM(CASE WHEN EVENTS = 3 THEN 1 ELSE 0 END)
FROM EVENTS_ID r WHERE r.ID = t.ID AND r.YEAR = 2012)
FROM (SELECT * FROM Events_ID GROUP BY ID) as t;
Is there anyway to get the output of the second query nearer to the speed of the first?
Is this what you want?
SELECT ID,
SUM(CASE WHEN EVENTS = 3 AND YEAR = 2012 THEN 1 END)
FROM Events_ID
GROUP BY ID;
This will return all ids, with a NULL as a second value if no events match both conditions.

SQL IN or EXISTS clause issue

I have two separate queries that I'd like to combine but I'm struggling to get the result I'd like. One summarizes all the values in the table and another selects duplicate rows based on the most recent date.
A shortened version of the first query is:
SELECT a.PLANT_NO "PlantNumber",
SUM(CASE WHEN a.REC_STATUS_CD = 'RR' THEN -a.KW_CTR_REDELIVERED_HV
ELSE a.KW_CTR_REDELIVERED_HV END) "KeepWholeResidueMMBtu",
SUM(a.ETH_APPLIED_POP_PCT + a.ISO_APPLIED_POP_PCT +
(CASE WHEN a.PLANT_NO = '002' THEN a.ALTLIQ_APPLIED_POP_PCT ELSE 0 END)
)/100 "NGLPOPPaymentPercent"
FROM GAS_STMT a
INNER JOIN SETTLE_SUMMARY c
ON CASE WHEN SUBSTR(a.TRNX_ID,1,1) = '-'
THEN SUBSTR(a.TRNX_ID, 2, LENGTH(a.TRNX_ID))
ELSE CAST(a.TRNX_ID AS VARCHAR2(100))
END = c.TRNX_ID
AND a.MTR_NO||a.MTR_SFX = c.MTR_NO||c.MTR_SFX
WHERE TO_CHAR(a.PROD_DT, 'YYYY') >= TO_CHAR(ADD_MONTHS(SYSDATE, -36), 'YYYY')
AND a.STATUS_UNIT_TM_CD = 'M'
GROUP BY a.PLANT_NO
ORDER BY a.PLANT_NO
The other query is used to filter out four transactions based on the most recent transaction date.
SELECT a.*
FROM GAS_STMT a,
(SELECT MTR_NO,MTR_SFX,TRNX_ID,REC_STATUS_CD,MAX(ACCT_DT) ACCT_DT
FROM GAS_STMT
WHERE REC_STATUS_CD = 'RR'
GROUP BY MTR_NO, MTR_SFX, TRNX_ID, REC_STATUS_CD
HAVING COUNT(TRNX_ID) > 1) b
WHERE a.MTR_NO = b.MTR_NO
AND a.TRNX_ID = b.TRNX_ID AND a.REC_STATUS_CD = b.REC_STATUS_CD
AND a.ACCT_DT = b.ACCT_DT
I would think that I could use where NOT IN or NOT EXISTS to have the first query sum everything except for those four records excluded in the second query.
Using EXISTS I get the same result as the first query by itself and using NOT EXISTS I get no results. When I use IN I get a sum of the excluded records which is the opposite of what I want.
Is there a good way to do this in PL/SQL? I'm confused that I'm not getting any records for the NOT EXISTS query.
Example of first query results:
Plant_No - Sum
002 - 100
450 - 50
500 - 50
Example of second query results:
Trnx_ID - Plant_no - KW_CTR_REDELIVERED_HV
1234 - 002 - -.99
1235 - 002 - -.99
Intended result:
Plant_No - Sum
002 - 98.02
450 - 50
500 - 50
If you want to exclude the records returned by the second query, try:
SELECT a.PLANT_NO "PlantNumber",
SUM(CASE WHEN a.REC_STATUS_CD = 'RR' THEN -a.KW_CTR_REDELIVERED_HV
ELSE a.KW_CTR_REDELIVERED_HV END) "KeepWholeResidueMMBtu",
SUM(a.ETH_APPLIED_POP_PCT + a.ISO_APPLIED_POP_PCT +
(CASE WHEN a.PLANT_NO = '002' THEN a.ALTLIQ_APPLIED_POP_PCT ELSE 0 END)
)/100 "NGLPOPPaymentPercent"
FROM GAS_STMT a
INNER JOIN SETTLE_SUMMARY c
ON CASE WHEN SUBSTR(a.TRNX_ID,1,1) = '-'
THEN SUBSTR(a.TRNX_ID, 2, LENGTH(a.TRNX_ID))
ELSE CAST(a.TRNX_ID AS VARCHAR2(100))
END = c.TRNX_ID
AND a.MTR_NO||a.MTR_SFX = c.MTR_NO||c.MTR_SFX
LEFT JOIN (SELECT MTR_NO,MTR_SFX,TRNX_ID,REC_STATUS_CD,MAX(ACCT_DT) ACCT_DT
FROM GAS_STMT
WHERE REC_STATUS_CD = 'RR'
GROUP BY MTR_NO, MTR_SFX, TRNX_ID, REC_STATUS_CD
HAVING COUNT(TRNX_ID) > 1) b
ON a.MTR_NO = b.MTR_NO
AND a.TRNX_ID = b.TRNX_ID
AND a.REC_STATUS_CD = b.REC_STATUS_CD
AND a.ACCT_DT = b.ACCT_DT
WHERE TO_CHAR(a.PROD_DT, 'YYYY') >= TO_CHAR(ADD_MONTHS(SYSDATE, -36), 'YYYY')
AND a.STATUS_UNIT_TM_CD = 'M'
AND b.MTR_NO IS NULL
GROUP BY a.PLANT_NO
ORDER BY a.PLANT_NO
Join b from the second query on to the first query the same way that the second query does it i.e.
inner join (SELECT MTR_NO,MTR_SFX,TRNX_ID,REC_STATUS_CD,MAX(ACCT_DT) ACCT_DT
FROM GAS_STMT
WHERE REC_STATUS_CD = 'RR'
GROUP BY MTR_NO, MTR_SFX, TRNX_ID, REC_STATUS_CD
HAVING COUNT(TRNX_ID) > 1) b
on a.MTR_NO = b.MTR_NO
AND a.TRNX_ID = b.TRNX_ID AND a.REC_STATUS_CD = b.REC_STATUS_CD
AND a.ACCT_DT = b.ACCT_DT
that way you get everything from the first query but only from the rows that would show up on the second query