SQL query counts returns the same number - sql

The following query:
Select t1.name
, t1.email
, t1.activated
, count(t2.id) as 'reporter'
, count(t3.id) as 'comments'
, count(t4.id) as 'reported'
from users t1
inner join tickets as t2 on t1.id = t2.reporter_id
inner join comments as t3 on t1.id = t3.user_id
inner join tickets as t4 on t1.id = t4.reported_id
group by name
The counts return all 3 the same number

It would be great to see sample data, current results and expect results.
But I'm guessing it's because your group by clause doesn't include the t1.email and t1.activated columns.
Select t1.name
, t1.email
, t1.activated
, count(t2.id) as 'reporter'
, count(t3.id) as 'comments'
, count(t4.id) as 'reported'
from users t1
inner join tickets as t2 on t1.id = t2.reporter_id
inner join comments as t3 on t1.id = t3.user_id
inner join tickets as t4 on t1.id = t4.reported_id
group by name
, t1.email
, t1.activated
Without sample data, it's hard to be sure, but I don't think your joins do what you want them to do. You will only get results for users who have are both "reported" and "reporter", and those tickets include at least 1 comment from the user who reported it.

count() returns the number of rows with non-NULL values. The ids are presumably NOT NULL so they return the same values.
The quick-and-dirty solution to your problem is to use COUNT(DISTINCT:
Select t1.name, t1.email, t1.activated,
count(distinct t2.id) as reporter,
count(distinct t3.id) as comments,
count(distinct t4.id) as reported
. . .
Do not use single quotes for column aliases! Only use single quotes for string and date constants.
Note that your query will never return 0 values for any of the counts. Also, this is more expensive than necessary. I am not providing a more efficient solution here, because the above answers your question. If you have other issues with the query, then ask a new question with appropriate sample data, desired results, and an explanation of what you want to do.

Related

sql DISTINCT with COALESCE

I am working with two tables in a database where the first table (T1) consist of measurements from a device and the other table (T2) has the information on each individual device.
In T2 there is a column called METADATA1 which could be a description, an empty string or null.
I would like to write a query that gets all the distinct devices that have measurements in T1 and their METADATA1. I want to replace the empty/null metadata with deviceid. Here is what I have
SELECT DISTINCT(t1.DEVICEID),
COALESCE(NULLIF(t2.METADATA1,''), t1.DEVICEID) AS METADATA1
FROM T1 t1 LEFT JOIN T2 t2 ON t1.DEVICEID = t2.DEVICEID
ORDER BY t1.DEVICEID ASC
This returns zero rows and does not work. If I replace the COALESCE with COALESCE(NULLIF(t2.METADATA1,''), '0') then I get the correct number of rows.
Could someone please tell me what I am doing wrong.
Your query should be returning rows, assuming t1 has rows. I would express it using GROUP BY rather than SELECT DISTINCT.
SELECT t1.DEVICEID,
COALESCE(NULLIF(MAX(t2.METADATA1), ''), t1.DEVICEID) AS METADATA1
FROM T1 t1 LEFT JOIN
T2 t2
ON t1.DEVICEID = t2.DEVICEID
GROUP BY t1.DEVICEID
ORDER BY t1.DEVICEID ASC;

Incorrect Syntax near the keyword On

I'm trying to make a query at work in which I count all occurrences of an id in one table and then I link the description and the colors associated with those ids from another.
But I seem to have botched up my SQL Syntax (it's been a while, sorry!). It's probably just a silly mistake and I'd be so greatful to whoever could help me out!
SELECT
t1.activity_status_id,
count(*),
t2.description,
t2.color
FROM
dbo.Activity t1
INNER JOIN (
dbo.Activity_Status t2 ON t1.activity_status_id = t2.id)
GROUP BY
activity_status_id
Just remove unnecessary brackets ( and ) around inner join:
SELECT ....
FROM
dbo.Activity t1
INNER JOIN dbo.Activity_Status t2 ON t1.activity_status_id = t2.id
GROUP BY ....
SELECT t1.activity_status_id,
Count(*),
t2.description,
t2.color
FROM dbo.Activity t1
INNER JOIN dbo.Activity_Status t2
ON t1.activity_status_id = t2.id
GROUP BY t1.activity_status_id ,t2.description,t2.color

Join where does not equal

I have two queries I have created in Access and I'm a step away from arriving at the data I need. I need to subset in some way.
Table1 and Table2 (Actually query1 and query2). They both have 3 fields: Email, Matcher and List.
I need to get all the results from Table2 where Email does not exist in Table1.
I found some posts about using an outer join and where null clause. I could not get it to work though. Didn't post what I tried here in case I was off course.
select t2.*
from table2 t2
left join table1 t1 on t2.email = t1.email
where t1.email is null
SELECT t2.*
FROM table2 t2
WHERE NOT EXISTS (
SELECT *
FROM table1 t1
WHERE t1.email = t2.email
)

SQL Joining three tables and using LEFT OUTER JOIN

I have three tables and two seperate SQL queries which are working correctly and I am having correct results.
If I try to join these three tables I am having null as result.
First query:
select T1.ID,T3.COMPANY
from T1,T3
where (T1.status!='CLOSED') and (T1.PRIORITY)>5 and T1.CLASSID=T3.CLASSID
Second query:
SELECT T1.ID, T2.DESCRIPTION
FROM T1
LEFT OUTER JOIN T2
ON T1.ID=T2.KEY
WHERE T1.status!='CLOSED'
AND (T2.CREATEDATE= (SELECT MAX(CREATEDATE)
FROM T2
WHERE T2.KEY=T1.ID))
I tried to join them but as result I am having null:
select T1.ID,T3.COMPANY,T2.DESCRIPTION
from T1
INNER JOIN T3 ON T1.CLASSID=T3.CLASSID
LEFT OUTER JOIN T2
ON T1.ID=T2.KEY
where (T1.status!='CLOSED') AND (T1.PRIORITY)>5
AND (T2.CREATEDATE= (SELECT MAX(CREATEDATE)
FROM T2
WHERE T2.KEY=T1.ID))
like it does not recognized last part for taking MAX value from T2 table.
What am I doing wrong? Thanks for help
Firstly, use an alias for the subquery on table T2.
T2.CREATEDATE =
(SELECT MAX(T2Alias.CREATEDATE)
FROM T2 AS T2Alias
WHERE T2Alias.KEY = T1.ID)
Secondly, consider moving this condition into the ON clause of the LEFT JOIN to table T2.
The first thing that jumps out at me is the new dependency on both T1.Priority > 5 and T2.CreateDate value being equal to the result of the inline query:
( AND (T1.PRIORITY) > 5
AND (T2.CREATEDATE =
(SELECT MAX(CREATEDATE) FROM T2 WHERE T2.KEY = T1.ID) )
Without the data it's difficult to check however this may be the issue

MySQL Join syntax for one to many relationship

I have a situation where I have one table of titles (t1) and another table with multiple links that reference these titles (t2) in a one to many relationship.
What I want is the full list of titles returned with a flag that indicates if there is a specific link associated with it.
Left Join and Group By:
SELECT
t1.id
, t1.title
, t2.link_id AS refId
FROM
t1
LEFT JOIN t2
ON (t1.id = t2.title_id)
GROUP BY t1.id;
This is close as it gives me either the first link_id or NULL in the refId column.
Now, how do I constrain the results if I have a specific link_id rather than allowing t2 run through the whole data set?
If I add a WHERE clause, for example:
WHERE t2.link_id = 123
I only get the few records where the link_id matches but I still need the full set of titles returned with NULL in the refId column unless link_id = 123.
Hope someone can help
Instead of in the WHERE clause, put your criteria in the LEFT JOIN clause:
SELECT
t1.id
, t1.title
, t2.link_id AS refId
FROM
t1
LEFT JOIN t2
ON t1.id = t2.title_id AND t2.link_id = 123
GROUP BY t1.id;
Put it in the join condition for the second table
SELECT t1.id, t1.title, t2.link_id as refId
FROM t1
LEFT JOIN t2 ON t1 = t2.title_id AND t2.link_id = 123
GROUP BY t1.id;