Need to create a case statement for multiple criteria with varchar and date data types - sql

Need to create a case statement for multiple criteria with varchar and date data types, my code sp far:
select
least(coalesce(case when 1.other_id=10 then 1.datestr else 0 end,
case when 2.info='Yes' then 2.date else 0 end))as date1,
from
test1 as 1
left join test2 as 2 on 1.id = 2.id
I essentially want to get the lowest date between 2 conditions. Both conditions have some filters (other_id=10 in first, info="Yes" in second). For those conditions I want to compare least dates.

I think this is the logic:
select (case when 1.other_id = 10 and 2.info = 'Yes'
then least(case when 1.other_id=10 then 1.datestr end,
case when 2.info='Yes' then 2.date end
)
when 1.other_id = 10 then 1.date
else 2.date
end)
Or, you can use more appropriate default values in your expression. Something like this (it might depend on the database):
select least(case when 1.other_id = 10 then 1.datestr else '9999-01-01' end,
case when 2.info = 'Yes' then 2.date else '9999-01-01' end)
) as date1,

Related

Combining multiple rows with the same ID, but different 'Yes'/'No' values for several columns, into one row showing all 'Yes'/'No' values

For the above table, I need to reduce the rows down to one per Filter ID and have all the possible yes/no values showing for that particular Filter Id
for example:
Filter ID
Outpatient Prescriptions
Opioid Outpatient Prescriptions
...
IP Pharmacy Medication Orders - Component Level
1
Yes
Yes
...
No
How is this achieved?
If I understand your question, for each partition of FilterID value, you want any field that has a yes to be aggregated up as 'Yes', otherwise 'No'. If you group by FilterID then you can handle the rollup using a CASE SUM CASE.
SELECT
FilterID,
Field1Response = CASE WHEN SUM(CASE WHEN Field1='Yes' THEN 1 ELSE 0 END) > 1 THEN 'Yes' ELSE 'No' END,
Field2Response = CASE WHEN SUM(CASE WHEN Field2='Yes' THEN 1 ELSE 0 END) > 1 THEN 'Yes' ELSE 'No' END ,
Field3Response = CASE WHEN SUM(CASE WHEN Field3='Yes' THEN 1 ELSE 0 END) > 1 THEN 'Yes' ELSE 'No' END
...
FROM
Data
GROUP BY
FilterID
By the nature of the data, you can also simply use a MAX. This is not a good habit of getting into because the values may change over time, however, if the values are always Y or N then you could simply use MAX:
SELECT
FilterID,
Field1Response = MAX(Field1),
Field2Response = MAX(Field1),
Field3Response = MAX(Field1)
...
FROM
Data
GROUP BY
FilterID

Is there a way to contruct this kind of result using group by in sql?

I have a table which consists of data where in I'm having trouble counting the corresponding rows.
Here is the sample table:
I am expecting an output like this:
You can do conditional aggregation:
select
sum(case when result = 'X' then 1 else 0 end) count_x,
sum(case when result is null then 1 else 0 end) count_blank
from mytable
I assume that by blank you mean null. If not, then you can change the condition in the second sum() from result is null to result = ''.
If you are running MySQL, this can be shortened a little:
select
sum(result = 'X') count_x,
sum(result is null) count_blank
from mytable

how do you check for nulls in any column in an entire table in SQL

I would like to check if any of my columns in a table have any null values. I am sure there is a quicker way than how I am doing it at the moment. I just want to see if there is a NULL in ANY column however my table has a lot of columns, is there a simple and quick way?
This way I have written so far works but it takes a long time to do for every column (hence the etc etc)
select
sum(case when id is null then 1 else 0 end) as id,
sum(case when name is null then 1 else 0 end) as name,
sum(case when review_count is null then 1 else 0 end) as review_coun,
sum(case when positive_review is null then 1 else 0 end) as
positive_review,
sum(etc etc
from user
I don't know if this will work for your scenario, but it's an option. You can CAST all your columns as a string and then concatenate them together. If you concatenate a NULL value with a string, it will return NULL.
SELECT 'Y'
WHERE EXISTS( -- Check if there are any NULL rows
SELECT
CAST(c1 AS CHAR(1)) ||
CAST(c2 AS CHAR(1)) ||
...
AS MyColumns
WHERE MyColumns IS NULL
)
;

Create Multiple Count Columns using Case When

I have to Case statements that count the same column just with a differnt criteria. The problem i am having is that the first case creates a null entry in the Test2 column but then counts it on my second case statement and leaves the Test 1 column null. I would like to have both counts side by side instead of created a duplicate row.
select m.no,
Case when itemtype = 'S' THEN count(ITEMKEY) end as Test1,
case when ItemType='C' THEN count(ITEMKEY) END as Test2
from test m
I'm pretty sure you want conditional aggregation. The case expression is an argument to the aggregation function:
select m.no,
sum(case when itemtype = 'S' then 1 else 0 end) as test1,
sum(case when itemtype = 'C' then 1 else 0 end) as test2
from test m
group by m.no;
This assumes that itemKey is never null, so the count() is just counting rows.
Following query can display records which having Itemtype 'S' or 'C' with count of itemkey. if itemkey is null it will display 0 else count of item key
select m.no,
Case when isnull( m.itemtype = 'S',0) THEN (select count(a.ITEMKEY) from test a where a.itemtype = 'S' ) else 0 end as Test1,
case when isnull( m.itemtype='C',0) THEN (select count(b.ITEMKEY) from test b where b.itemtype = 'C') else 0 END as Test2
from test m

Issues with counting records in secondary table based on complex criteria

I need to be able to count the number of records in a secondary table tblOptyRecordsHistorical which are related to the main table tblOptyRecordsCurrent.
The tables are exactly the same, the main contains the current 'daily snapshot', the secondary table contains previous daily snapshots.
I have a number of flags which use the following basic syntax:
(SELECT COUNT(OpportunityRecordID) AS Expr1
FROM dbo.tblOptyRecordsHistorical AS hist
WHERE (OpportunityGlobalCRMId = curr.OpportunityGlobalCRMId))
AS prevEntries,
This works fine. But one flag, I need to count the number of records in the historical table, but the logic is more complicated and depends on values from the main table:
SELECT OpportunityGlobalCRMId,
(SELECT SUM(CASE WHEN curr.PartnerGlobalCRMID IS NULL THEN CASE WHEN
hist.IgnoreOpportunity != 0 THEN 1 ELSE 0 END ELSE CASE
WHEN curr.CustomerAccountID IS NULL THEN CASE WHEN hist.IgnoreOpportunity = 1 AND
hist.PartnerGlobalCRMID = curr.PartnerGlobalCRMID THEN 1 ELSE 0 END ELSE CASE WHEN
hist.IgnoreOpportunity = 1 AND CONVERT(varchar, hist.CustomerAccountID) +
hist.PartnerGlobalCRMID = CONVERT(varchar, curr.CustomerAccountID) +
curr.PartnerGlobalCRMID AND hist.OpptyIncentiveCreatedDate =
curr.OpptyIncentiveCreatedDate THEN 1 ELSE 0 END END END) AS Expr1 FROM
dbo.tblOptyRecordsHistorical AS hist WHERE (OpportunityGlobalCRMId =
curr.OpportunityGlobalCRMId)) AS prevIgnored
FROM dbo.tblOptyRecordsCurrent AS curr
I've omitted the other flags and fields except for the initial OpportunityGlobalCRMID. This results in the following error: Multiple columns are specified in an aggregated expression containing an outer reference. If an expression is being aggregated contains an outer reference, then that outer reference must be the only column referenced in the expression.
SQL Server does not like mixing of inner (hist table) and outer (curr table) in a aggregate subquery expression. Some explanation is available here.
The proposed solutuon is to re-include the outer table in the sub-query, joining on it's key, in order to make all references inner. In your case, that would mean putting the tblOptyRecordsCurrent table inside the subquery, like this:
SELECT OpportunityGlobalCRMId,
(SELECT SUM(CASE
WHEN curr2.PartnerGlobalCRMID IS NULL
THEN CASE WHEN hist.IgnoreOpportunity != 0 THEN 1 ELSE 0 END
ELSE CASE
WHEN curr2.CustomerAccountID IS NULL
THEN CASE
WHEN hist.IgnoreOpportunity = 1 AND hist.PartnerGlobalCRMID = curr2.PartnerGlobalCRMID THEN 1 ELSE 0 END
ELSE CASE
WHEN hist.IgnoreOpportunity = 1
AND CONVERT(varchar, hist.CustomerAccountID) + hist.PartnerGlobalCRMID
= CONVERT(varchar, curr2.CustomerAccountID) + curr2.PartnerGlobalCRMID
AND hist.OpptyIncentiveCreatedDate = curr2.OpptyIncentiveCreatedDate
THEN 1
ELSE 0
END
END
END) AS Expr1
FROM dbo.tblOptyRecordsHistorical AS hist
inner join dbo.tblOptyRecordsCurrent AS curr2 on curr2.OpportunityGlobalCRMId = hist.OpportunityGlobalCRMId
WHERE curr2.OpportunityGlobalCRMId = curr.OpportunityGlobalCRMId) AS prevIgnored
FROM dbo.tblOptyRecordsCurrent AS curr
Haven't tested the code however.