Count DIFFDATE Exceeding A Specified Value - Step 2 - sql

Further to my earlier question. Now I have two different queries that work. The first query returns a result of 5092 and the second returns a result of 1885 adding up to 6977. I would like to combine them into one query to return a result of 6977. How can I make one query count the number of conditionassessmentdates that are active, overdue by more than 14 days and null (counts as overdue)? Thanks in advance.
select count (*)
from task_conditionassessment t
inner join taskitems_conditionassessment ti on
t.task_conditionassessmentguid=ti.task_conditionassessmentguid
inner join conditionassessmentassignmentitem c on
ti.taskitems_conditionassessmentid=c.taskitems_conditionassessmentid
where datediff(dd,c.conditionassessmentdate,t.nextduedate)>14 and t.isactive=1
select t.taskname,t.nextduedate,c.conditionassessmentdate
from task_conditionassessment t
inner join taskitems_conditionassessment ti on
t.task_conditionassessmentguid=ti.task_conditionassessmentguid
inner join conditionassessmentassignmentitem c on
ti.taskitems_conditionassessmentid=c.taskitems_conditionassessmentid
where c.conditionassessmentdate IS NULL and t.isactive=1

If you just want a count of records that fit either set of criteria, just use an or in your where clause:
select count (*)
from task_conditionassessment t
inner join taskitems_conditionassessment ti on
t.task_conditionassessmentguid=ti.task_conditionassessmentguid
inner join conditionassessmentassignmentitem c on
ti.taskitems_conditionassessmentid=c.taskitems_conditionassessmentid
where (c.conditionassessmentdate IS NULL or
datediff(dd,c.conditionassessmentdate,t.nextduedate)>14) and
t.isactive=1

Providing that I understand correctly, just OR the two conditions together:
select count (*)
from task_conditionassessment t
inner join taskitems_conditionassessment ti on t.task_conditionassessmentguid=ti.task_conditionassessmentguid
inner join conditionassessmentassignmentitem c on ti.taskitems_conditionassessmentid=c.taskitems_conditionassessmentid
where (datediff(dd,c.conditionassessmentdate,t.nextduedate)>14
or c.conditionassessmentdate IS NULL)
and t.isactive=1

Related

Three tables with two counts with group by

In my query I want total file count and total closed files in the same table.
My first query:
select hi.eksper_id,ef.ad, count(hi.eksper_id) as total_files
from hasar_ihbar as hi
left outer join eksper_firma ef on ef.id=hi.eksper_id
group by hi.eksper_id,ef.ad
My second query:
select ef.id as eksper_id,ef.ad,count(ef.id) closed_files
from hasar_ihbar_rapor hir
left outer join hasar_ihbar hi on hi.id = hir.hasar_ihbar_id
left outer join eksper_firma ef on ef.id = hi.eksper_id
where hir.rapor_tipi = 3 group by ef.id,ef.ad
I want both combined and this is my code:
select ef.id as eksper_id,ef.ad,count(ef.id) closed_files, count(hi.id) AS total_files
from hasar_ihbar_rapor hir
left outer join hasar_ihbar hi on hi.id = hir.hasar_ihbar_id
left outer join eksper_firma ef on ef.id = hi.eksper_id
where hir.rapor_tipi = 3 group by ef.id,ef.ad
I don't know what I did wrong. Thanks for your help.
The double joins effect your counts since there are more rows.
A better way to combine both counts is to create a query that has two subqueries for each count.
SELECT id,
(SELECT COUNT(*)...) total_files,
(SELECT COUNT(*)...) closed_files
FROM ...

SQL query with 2 counts and 2 left outer joins

Im trying to show all columns from my t1_elem table and join 2 columns in which I use COUNT.
I used query:
SELECT p.*,COUNT(t4_id) as ile_publikacji, COUNT(t7_id) as ile_fitow
FROM t1_elem p
LEFT OUTER JOIN t4_autorzy ON p.t1_id=t4_autorzy.t4_t1_id
LEFT JOIN t7_pliki ON p.t1_id=t7_pliki.t7_t1_id
GROUP BY t1_id
But the results are bad. What I'm doing wrong?
Probably you have multiple matches. As stated, the two counts will be the same. The simplest solution is probably to use distinct:
SELECT p.*, COUNT(DISTINCT t4_id) as ile_publikacji, COUNT(DISTINCT t7_id) as ile_fitow
FROM t1_elem p LEFT JOIn
t4_autorzy
ON p.t1_id = t4_autorzy.t4_t1_id LEFT JOIN
t7_pliki
ON p.t1_id=t7_pliki.t7_t1_id
GROUP BY t1_id

How to use count with Distinct ON

I have this query that already works, i need to write count query for this (need pagination), and i have issues using count with DISTINCT ON, anyone knows correct syntax and way to use it, i already googled but was not able to find any count queries with DISTINCT ON
As result i'm expecting total number of rows from this query that already works
select DISTINCT on (csd.team_contest_id)
c.id as contestId
from contest as c
left join company_sponsor_team as csd on csd.contest_id = c.id
left join sponsor as s on s.id = c.sponsor_id
left join team as d on d.id = c.team_id
left join player as m on c.creator_id = m.id
WHERE c.id = c.id
AND ((c.team_id is not null and c.sponsor_id is null and lower(d.name) LIKE LOWER(CONCAT('%TAN%')))
OR (c.team_id is not null and c.sponsor_id is not null and lower(s.name) LIKE LOWER(CONCAT('%TAN%')))
OR (c.team_id is null and lower(s.name) LIKE LOWER(CONCAT('%TAN%')))) AND (CURRENT_DATE < c.archive_date)
If you want to count the number of rows, use a subquery:
select count(*)
from ( <your query here> ) x;
If you have an aversion to subqueries, you can always do:
select count(distinct csd.team_contest_id)
from . . . <the rest of your query here>;
This returns the same value assuming that csd.team_contest_id is not NULL.

SQL Get aggregate as 0 for non existing row using inner joins

I am using SQL Server to query these three tables that look like (there are some extra columns but not that relevant):
Customers -> Id, Name
Addresses -> Id, Street, StreetNo, CustomerId
Sales -> AddressId, Week, Total
And I would like to get the total sales per week and customer (showing at the same time the address details). I have come up with this query
SELECT a.Name, b.Street, b.StreetNo, c.Week, SUM (c.Total) as Total
FROM Customers a
INNER JOIN Addresses b ON a.Id = b.CustomerId
INNER JOIN Sales c ON b.Id = c.AddressId
GROUP BY a.Name, c.Week, b.Street, b.StreetNo
and even if my SQL skill are close to none it looks like it's doing its job. But now I would like to be able to show 0 whenever the one customer don't have sales for a particular week (weeks are just integers). And I wonder if somehow I should get distinct values of the weeks in the Sales table, and then loop through them (not sure how)
Any help?
Thanks
Use CROSS JOIN to generate the rows for all customers and weeks. Then use LEFT JOIN to bring in the data that is available:
SELECT c.Name, a.Street, a.StreetNo, w.Week,
COALESCE(SUM(s.Total), 0) as Total
FROM Customers c CROSS JOIN
(SELECT DISTINCT s.Week FROM sales s) w LEFT JOIN
Addresses a
ON c.CustomerId = a.CustomerId LEFT JOIN
Sales s
ON s.week = w.week AND s.AddressId = a.AddressId
GROUP BY c.Name, a.Street, a.StreetNo, w.Week;
Using table aliases is good, but the aliases should be abbreviations for the table names. So, a for Addresses not Customers.
You should generate a week numbers, rather than using DISTINCT. This is better in terms of performance and reliability. Then use a LEFT JOIN on the Sales table instead of an INNER JOIN:
SELECT a.Name
,b.Street
,b.StreetNo
,weeks.[Week]
,COALESCE(SUM(c.Total),0) as Total
FROM Customers a
INNER JOIN Addresses b ON a.Id = b.CustomerId
CROSS JOIN (
-- Generate a sequence of 52 integers (13 x 4)
SELECT ROW_NUMBER() OVER (ORDER BY a.x) AS [Week]
FROM (VALUES(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1)) a(x)
CROSS JOIN (SELECT x FROM (VALUES(1),(1),(1),(1)) b(x)) b
) weeks
LEFT JOIN Sales c ON b.Id = c.AddressId AND c.[Week] = weeek.[Week]
GROUP BY a.Name
,b.Street
,b.StreetNo
,weeks.[Week]
Please try the following...
SELECT Name,
Street,
StreetNo,
Week,
SUM( CASE
WHEN Total IS NULL THEN
0
ELSE
Total
END ) AS Total
FROM Customers a
JOIN Addresses b ON a.Id = b.CustomerId
RIGHT JOIN Sales c ON b.Id = c.AddressId
GROUP BY a.Name,
c.Week,
b.Street,
b.StreetNo;
I have modified your statement in three places. The first is I changed your join to Sales to a RIGHT JOIN. This will join as it would with an INNER JOIN, but it will also keep the records from the table on the right side of the JOIN that do not have a matching record or group of records on the left, placing NULL values in the resulting dataset's fields that would have come from the left of the JOIN. A LEFT JOIN works in the same way, but with any extra records in the table on the left being retained.
I have removed the word INNER from your surviving INNER JOIN. Where JOIN is not preceded by a join type, an INNER JOIN is performed. Both JOIN and INNER JOIN are considered correct, but the prevailing protocol seems to be to leave the INNER out, where the RDBMS allows it to be left out (which SQL-Server does). Which you go with is still entirely up to you - I have left it out here for illustrative purposes.
The third change is that I have added a CASE statement that tests to see if the Total field contains a NULL value, which it will if there were no sales for that Customer for that Week. If it does then SUM() would return a NULL, so the CASE statement returns a 0 instead. If Total does not contain a NULL value, then the SUM() of all values of Total for that grouping is performed.
Please note that I am assuming that Total will not have any NULL values other than from the RIGHT JOIN. Please advise me if this assumption is incorrect.
Please also note that I have assumed that either there will be no missing Weeks for a Customer in the Sales table or that you are not interested in listing them if there are. Again, please advise me if this assumption is incorrect.
If you have any questions or comments, then please feel free to post a Comment accordingly.

Additional inner join modifying results of previous calculations

I am having issues with using the count() function in an sql plus query.. say if
SELECT B.ID COUNT(S.BRANCH_ID) FROM BRANCH B
INNER JOIN STAFF S ON S.BRANCH_ID = B.ID
GROUP BY B.ID;
from doing this I'll get the results
b.id count
1 6
2 6
3 6
4 7
5 6
which is fine.. However if I even add an extra inner join i'll get completely different and wrong results.. So if I put for example..
SELECT COUNT(S.BRANCH_ID) FROM BRANCH B
INNER JOIN STAFF S ON S.BRANCH_ID = B.ID
INNER JOIN TOOL_STOCK TS ON TS.BRANCH_ID = B.ID
GROUP BY B.ID;
Now the results I get will be...
b.id count
1 96
2 96
3 96
4 112
5 96
Why is this and how do I stop it? Cheers!
Try
SELECT B.ID, COUNT(DISTINCT S.STAFF_ID) FROM BRANCH B
INNER JOIN STAFF S ON S.BRANCH_ID = B.ID
INNER JOIN TOOL_STOCK TS ON TS.BRANCH_ID = B.ID
GROUP BY B.ID;
replacing S.STAFF_ID with the primary key field from the STAFF table.
Your problem is that the COUNT function returns the number of rows matching the GROUP BY clause after all rows have been joined and returned.
In your initial query you are finding the number of employees for each branch, In the second the number of employees is multiplied by the number of stock items.
When you add the second join, you are getting the counts for STAFF + TOOLS at each branch.
You will likely need to add a subquery if you want all the data returned, but only counts of one record type.
I think the key to your issue is, which are you actually trying to count?