DAX - count attributes for which FACT records do not exist - sql

I am looking for a DAX measure that is equal to If i have in SQL:
SELECT COUNT(NoDataValue WHEN -1 THEN 1 ELSE 0 END)
FROM
(
SELECT Employee.EmployeeID, CASE WHEN FACT.EmployeeID IS NULL
THEN -1
ELSE 1
END as NoDataValue
FROM Employee LEFT OUTER JOIN FACT
On Employee.EmployeeID = FACT.EmployeeID
) X
Essentially i want -1 when there is no data for an employee at the row level but when its aggregated i need count of NoDataValues (How many employees did not have data).
That is working fine at employee level with the measure i created
Annual Independence Compliance No Data:=
  Var NoData=
  SUM ( [NoDataValue] )
RETURN (IF (ISBLANK(NoData) , -1, NoData))
This looks like
But this is not aggregating the counts. I am having trouble of how to do that. This shows up as

I'm not sure if you SQL query is returning what you want but the query should look like below
SELECT SUM(case NoData WHEN -1 THEN 1 ELSE 0 END) as NoDataCount
FROM
(
SELECT Employee.EmployeeID, CASE WHEN FACT.EmployeeID IS NULL
THEN -1
ELSE 1
END as NoData
FROM Employee LEFT OUTER JOIN FACT
On Employee.EmployeeID = FACT.EmployeeID
) X
or
SELECT SUM(IIF(NoData = -1,1,0)) as NoDataCount

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;

check and compare the count from two tables without relation

I have below tables
Table1: "Demo"
Columns: SSN, sales, Create_DT,Update_Dt
Table2: "Agent"
Columns: SSN,sales, Agent_Name, Create_Dt, Update_DT
Scenario 1 and desired result set:
I want output as 0 if the count of SSN in Demo table is matched with the count of SSN in Agent table
if the count is not matched then I want result as 1
Scenario 2 and desired result set:
I want output as 0 if the sum of sales in Demo table is matched with the sum of sales in Agent table
if the sum is not matched then I want result as 1
Please help on this query part
Thanks
You can write two queries separately to take counts within the result query
SELECT (SELECT count(Demo.SSN) as SSN1 from Demo)!=(SELECT count(Agent.SSN) as SSN2 from Agent) AS Result;
Basically what the inner queries does is it checked whether the counts are equal or not and outputs 1 if it is true and 0 if it is false. Since you have asked to output 1 if it is false I used '!=' sign.
You can try the same procedure in scenario 2 also
For scenario 1
select (Case when (select count(ssn) from Demo)=(select count(ssn) from Agent) then 0 else 1 end) as desired_result
If you want to count unique ssn then:
select (Case when (select count(distinct ssn) from Demo)=(select count(distinct ssn) from Agent) then 0 else 1 end) as desired_result
For scenario 2:
select (Case when (select sum(sales) from Demo)=(select sum(sales) from Agent) then 0 else 1 end) as desired_result
I would suggest one query with both sets of information:
select (d.num_ssn <> a.num_ssn) as have_different_ssn_count,
(d.sales <> a.sales) as have_different_sales
from (select count(distinct ssn) as num_ssn,
coalesce(sum(sales), 0) as sales
from demo
) d cross join
(select count(distinct ssn) as num_ssn,
coalesce(sum(sales), 0) as sales
from agent
) a;
Note: This returns boolean values -- true/false rather than 1/0. If you really want 0/1, then use case:
select (case when d.num_ssn <> a.num_ssn then 1 else 0 end) as have_different_ssn_count,
(case when d.sales <> a.sales then 1 else 0 end) as have_different_sales
It would not surprise me if you were not only interested in the total counts but also that the agent/sales combinations are the same in both tables. If that is the case, please ask a new question with a clear explanation. Sample data and desired results help.

How to do a COUNT with a WHERE clause?

I actually have a query joining 3 tables to collect informations so I can calculate some KPIs, but my logic is flawed, here is my actual query :
SELECT t.idCustomer, t.nameCustomer
COUNT(DISTINCT t.idTrip),
SUM(
CASE
WHEN t.tripDone <> 1
THEN 1
ELSE 0
END),
SUM(CASE
WHEN t.codeIncident = 'CANCEL'
THEN 1
ELSE 0
END)
FROM
(SELECT customer.idCustomer, customer.nameCustomer, trip.tripDone, incident.codeIncident
FROM CUSTOMER customer
JOIN TRIP trip ON customer.idCustomer = trip.idCustomer
JOIN INCIDENT incident ON trip.idTrip = incident.idTrip) t
GROUP BY t.idCustomer, t.nameCustomer
So, I want to know for each Customer :
COUNT(DISTINCT t.idTrip) -> The number of trips by this customer
Sum when t.tripDone <> 1 -> The number of trips that are done by this customer ( not ingoing )
Sum when t.codeIncident = 'CANCEL' -> The number of trips by this customer where there was a cancellation.
The big mistake I made here, is that a trip can have multiple codeIncidents (example : one record for an idTrip with the codeIncident 'CANCEL' and another record with same idTrip with the codeIncident 'DELAYED'), so when I calculate the Sum when t.tripDone <> 1 I get a result of : '2' instead of '1' (because there are 2 records in my from Clause that have the t.tripDone <> 1 for the same idTrip).
Would you have any idea on how I should process this query so I can do the Sum when tripDone <> 1 only once for each tripId ?
Thanks a lot for the help !
If you need some more infos I'm available, and sorry for my lack of english skills !
It sounds like you want to do the same count(distinct ...) pattern for the columns you're currently summing, but with some logic. You can use case within a count instead in the same way:
...
COUNT(
DISTINCT CASE
WHEN t.tripDone <> 1
THEN t.idTrip
ELSE null
END),
COUNT(
DISTINCT CASE
WHEN t.codeIncident = 'CANCEL'
THEN t.idTrip
ELSE null
END)
The else null is a bit redundant as that's the default. As count() ignores nulls, if the when isn't matched then that trip ID isn't counted.
First Select idTrip field in your inner query that means table "t"

SQL Query for sorting by number of identical values in column

I am attempting to write an sql query for Postgresql that looks through a table of descriptions for a subject and another table that keeps tally of how many likes or dislikes or other flags are attached to the description. I want it to go through the tally table, find all the flags attached to each description, find the sum of how many identical flags there are for each description, then order by the number of likes each flag has minus how many dislikes etc it has, then return a list of all descriptions ordered by the sum of the previously described equation ( likes - dislikes etc.) and the number of likes, dislikes, etc. this is an example of the code I have so far ( there are more variables in the likes/dislikes as variable section ):
SELECT likes, dislikes, positive - negative AS orderCondition
FROM( SELECT d.id, d.l_id, d.user_id, d.description, a.flaggee_id,
SUM( CASE WHEN a.actions_id = 1 THEN 1 WHEN actions_id = 6 THEN 1 ELSE 0 END ) AS positive,
SUM( CASE WHEN a.actions_id <> 1 THEN 1 WHEN a.actions_id <> 6 THEN 1 ELSE 0 END ) AS negative,
SUM( CASE WHEN a.actions_id = 1 THEN 1 ELSE 0 END ) AS likes,
SUM( CASE WHEN a.actions_id = 2 THEN 1 ELSE 0 END ) AS dislikes
FROM descriptions d, description_actions a
WHERE d.id = a.flaggee_id OR d.id > 0 AND d.id <> a.flaggee_id
GROUP BY d.id, a.flaggee_id ) as result
ORDER BY orderCondition DESC;
this is not working however, it returns an empty set without errors. data in the tables are random for testing, id's are integers, things that are not id's are random strings, when querying the tables individually the results are accurate, so its not a case of the data not being in the tables. I'm having a really difficult time figuring it out.. any help would be appreciated.
I figured it out, I needed to specify that it was a left join, in order to still display results if the flags table was empty, I also added variables to the outer select. here is the working query
SELECT description, likes, dislikes, positive - negative AS orderCondition
FROM( SELECT d.id, d.l_id, d.user_id, d.description AS description, a.flaggee_id,
SUM( CASE WHEN a.actions_id = 1 THEN 1 WHEN actions_id = 6 THEN 1 ELSE 0 END ) AS positive,
SUM( CASE WHEN a.actions_id <> 1 THEN 1 WHEN a.actions_id <> 6 THEN 1 ELSE 0 END ) AS negative,
SUM( CASE WHEN a.actions_id = 1 THEN 1 ELSE 0 END ) AS likes,
SUM( CASE WHEN a.actions_id = 2 THEN 1 ELSE 0 END ) AS dislikes
FROM descriptions d LEFT JOIN description_actions a ON a.flaggee_id = d.id
GROUP BY d.id, a.flaggee_id ) as result
ORDER BY orderCondition DESC;

Return records that all match and all records where at least one doesn't match

Given a table of exam results, where 1 == PASS and 0 == FAIL
ID Name Test Result
--------------------
1 John MATH 1
2 John ENGL 1
3 Mary MATH 1
4 Mary PSYC 0
EDIT: assume that the name is unique.
I need to get all records for people who
1) passed all tests
2) failed at least one test
So, the 1st query should return John and all his records, and the 2nd query should return Mary and all her records (including the ones with PASS).
I'm trying to do a LEFT OUTER JOIN with itself and compare counts, but don't seem to get a working query.
SELECT * FROM Results R1
LEFT OUTER JOIN Results R2 on R1.ID=R2.ID and R2.Result=1
WHERE ??? count of rows from R1 is compared to count of non-null rows from R2
This is a "poster-child" exercise for the EXISTS clause:
At leasr one failed result:
select * from Results r
where exists (select * from Results rr where rr.Name=r.Name AND Result=0)
All passed:
select * from Results r
where not exists (select * from Results rr where rr.Name=r.Name AND Result=0)
See how these queries work on your data set at sqlfiddle.com.
All passed
SELECT Name FROM Results R1
GROUP BY NAME
HAVING SUM(RESULT) = COUNT(RESULT)
Some failed
SELECT Name FROM Results R1
GROUP BY NAME
HAVING SUM(RESULT) < COUNT(RESULT)
Hope it helps
Edit
All passed
SELECT Name FROM Results R1
GROUP BY NAME
HAVING SUM(1-RESULT) = 0
Some failed
SELECT Name FROM Results R1
GROUP BY NAME
HAVING SUM(1-RESULT) > 0
(This might run faster)
One way
Select Name,
Case failCount When 0 then 'X' Else '' End PassedAll,
Case failCount When 0 then '' Else 'X' End FailedOneOrMore
From (Select name,
Sum(Case Result when 0 Then 1 Else 0 End) failCount
From Results R
Group By Name) Z
to get all the records, just join to this
Select zz.Name, zz.PassedAll, zz.FailedOneOrMore,
r.Test, r.Result
From (Select Name,
Case failCount When 0 then 'X' Else '' End PassedAll,
Case failCount When 0 then '' Else 'X' End FailedOneOrMore
From (Select name,
Sum(Case Result when 0 Then 1 Else 0 End) failCount
From Results R
Group By Name) Z) ZZ
Left Join Results r On r.Name = zz.Name
This query uses a subquery to return all records (pass & fail) for people who have passed at least one of the Tests:
select * from Results where Name in (select Name from Results where Result = '1' group by Name);
Results exclude those who failed to pass any of the tests.