How can I count the same fields - sql

I'm making a query to get the stages of a case. So Now I have three cases with 3 stages (the last stage inserted in the table user_case_stage).
SELECT DISTINCT ON (c.id)
c.id,
f.name
FROM schema.user a
JOIN schema.intern_user b ON a.id = b."userId"
JOIN schema.user_case c ON b.id = c."internUserId"
JOIN schema.user_case_stage d ON c.id = d."userCaseId"
JOIN schema.stage f ON d."stageId" = f.id
WHERE b.id = 1
ORDER BY c.id,d."createdAt" DESC
Result:
caseId stageName
1 "Pasive"
6 "Closed"
7 "Closed"
But I want something to count by stageName like this:
total stageName
1 "Pasive"
2 "Closed"

assumed your logic is correct , since you didn't provide any information, here is how you can do it:
SELECT
f.name
, count(distinct c.id) total
FROM schema.user a
JOIN schema.intern_user b ON a.id = b."userId"
JOIN schema.user_case c ON b.id = c."internUserId"
JOIN schema.user_case_stage d ON c.id = d."userCaseId"
JOIN schema.stage f ON d."stageId" = f.id
WHERE b.id = 1
group by f.name

Related

SQL Select count of items from a child table with a where clause

SQL Query :
select c.cid, la.lid, b.bid, b.type
from c c
left join la la on c.cid = la.cid
left join b b on la.lid = b.lid
where b.type = 'Primary';
There are three tables c -> la -> b
I need the total count of 'b' for any given 'la' but I need to have " b.type = 'Primary' " in the where clause for other purposes.
b.type has two types - Primary and Secondary but I want a count of total number of 'b' (Primary and Secondary) Can somebody give any hints ? It would be a good learning for me. Thanks.
sample data and desired o/p
Try this:
SELECT
c.cid,
la.lid,
b.bid,
b.type,
d.cbdi
FROM c c
LEFT JOIN la la ON c.cid = la.lid
LEFT JOIN b b ON la.lid2 = b.lid2
LEFT JOIN (
SELECT
la.lid,
COUNT(b.bid) AS cbid
FROM la la
LEFT JOIN b b ON la.lid2 = b.lid2
GROUP BY la.lid
) d ON la.lid = d.lid
WHERE
b.type = 'Primary';
You can not have row having secondary in desired output as per your attached screenshot because of clause where b.type = 'Primary'. Please check again, looks like your requirement is not clear.
You seem to want to show all rows unaggregated but show an aggregation (the b count) along. This is done with a window function, COUNT OVER in your case.
select c.cid, la.lid, b.bid, b.type, count(*) over (partition by la.lid) as number_of_b
from la
join c on c.cid = la.cid
join b on b.lid = la.lid
order by c.cid, la.lid, b.bid;
If you want to restrict this to la that have at least one primary b, extend this query accordingly:
select cid, lid, bid, type, number_of_b
from
(
select
c.cid, la.lid, b.bid, b.type,
count(*) over (partition by la.lid) as number_of_b,
max(case when b.type = 'Primary' then 1 else 0 end) over (partition by la.lid)
as has_primary_b
from la
join c on c.cid = la.cid
join b on b.lid = la.lid
order by c.cid, la.lid, b.bid
)
where has_primary_b = 1;
One solution would be to join table b twice on for selecting only the Primary records and one to count all. Something like:
select c.cid, la.lid, count(bt.id)
from c c
join la la on c.cid = la.cid
join b b on la.lid = b.lid
join b bt on la.lid = bt.lid
where b.type = 'Primary'
group by c.cid, la.lid;

Select an ID where there is only one row and that row is a specific value

I have this query. There's a lot of joins because I am checking if an ID is linked to any of those tables.
Currently, this query shows me any ID's that are not linked to any of those tables. I would like to add to it so that it also shows any IDs that are linked to the d table, but only if there is only 1 row in the D table and the type in the D field is 'member'.
SELECT
c.ID,
c.location,
c.pb,
c.name,
c.surname
FROM c
LEFT JOIN l on c.rowno = l.rowno
LEFT JOIN d on c.rowno = d.rowno
LEFT JOIN t on c.rowno = t.rowno
LEFT JOIN cj ON (c.rowno = cj.rowno OR c.rowno = cj.rowno2)
LEFT JOIN dj ON c.rowno = d.rowno
LEFT JOIN lg ON c.rowno = lg.rowno
LEFT JOIN tj ON c.rowno = tj.rowno
WHERE
c.status != 'closed'
AND l.rowno IS NULL
AND d.rowno IS NULL
AND t.rowno IS NULL
AND cj.rowno IS NULL
AND dj.rowno IS NULL
AND lg.rowno IS NULL
AND tj.rowno IS NULL
My first thought is to just add
WHERE D.type = 'member'
But that gives me all IDs that have a row with D.type = member (they could have 10 rows with all different types, but as long as 1 of those has type = member it shows up). I want to see ID's that ONLY have d.type = member
I'm sorry if I'm wording this badly, I'm having trouble getting this straight in my head. Any help is appreciated!
I would use exists for all conditions except the one on the D table:
SELECT c.*
FROM c JOIN
(SELECT d.rownum, COUNT(*) as cnt,
SUM(CASE WHEN d.type = 'Member' THEN 1 ELSE 0 END) as num_members
FROM t
GROUP BY d.rownum
) d
ON c.rownum = d.rownum
WHERE c.status <> 'closed' AND
NOT EXISTS (SELECT 1 FROM t WHERE c.rowno = t.rowno) AND
NOT EXISTS (SELECT 1 FROM l WHERE c.rowno = l.rowno) AND
. . .
I find NOT EXISTS is easier to follow logically. I don't think there is a big performance difference between the two methods in SQL Server.

First query data is used in second query

I have a query get_product:
select A.product_id,
A.name, A.description, A.type_id,
B.series_name
product_data A
inner join
series B
on A.series_raw_id = B.series_raw_id
where A.product_id = 503061
and A.registration_type_id = 4
order by B.series_name
and second query
select B.series_name,
A.TEMPACC_STATUS
FROM
ACCESS_FACT A
inner join
**get_product** B
on A.TEMPACC_PRODUCT_ID = B.product_id
where A.TEMPACC_DATE_ID between 6717 and 6808
and A.reason_id_total = 0
group by Series_name,
STATUS
In the second query we use data from first query (get_product is the first query). How do I get that table here?
You could use the WITH clause.
For example,
WITH get_product AS
(SELECT A.product_id,
A.name,
A.description,
A.type_id,
B.series_name product_data A
INNER JOIN series B
ON A.series_raw_id = B.series_raw_id
WHERE A.product_id = 503061
AND A.registration_type_id = 4
ORDER BY B.series_name
)
SELECT B.series_name,
A.TEMPACC_STATUS
FROM ACCESS_FACT A
INNER JOIN get_product B
ON A.TEMPACC_PRODUCT_ID = B.product_id
WHERE A.TEMPACC_DATE_ID BETWEEN 6717 AND 6808
AND A.reason_id_total = 0
GROUP BY Series_name,
STATUS;
Or, you could use an INLINE VIEW
SELECT B.series_name,
A.TEMPACC_STATUS
FROM ACCESS_FACT A
INNER JOIN
(SELECT A.product_id,
A.name,
A.description,
A.type_id,
B.series_name product_data A
INNER JOIN series B
ON A.series_raw_id = B.series_raw_id
WHERE A.product_id = 503061
AND A.registration_type_id = 4
ORDER BY B.series_name
) B ON A.TEMPACC_PRODUCT_ID = B.product_id
WHERE A.TEMPACC_DATE_ID BETWEEN 6717 AND 6808
AND A.reason_id_total = 0
GROUP BY Series_name,
STATUS;

Left Join Yielding no results

I'm coming across an issue where when I write a query as so:
SELECT a.v, b.w, c.x, d.y, e.z
FROM a
JOIN b
on a.id = b.id
LEFT JOIN c
on a.id = c.id
LEFT JOIN d
on b.code=d.code
JOIN e
on a.n = e.n
WHERE
a.zone = 10
WITH (nolock)
I get several hundred results, but when I modify it to this:
SELECT a.v, b.w, c.x, d.y, e.z
FROM a
JOIN b
on a.id = b.id
LEFT JOIN c
on a.id = c.id AND c.n = 0
LEFT JOIN d
on b.code=d.code AND d.n = 0
JOIN e
on a.n = e.n
WHERE
a.zone = 10
WITH (nolock)
I get zero results.
From my understanding of SQL and left joins, I feel that getting any results with the first query means I should definitely get at least one result with the second, if only one where fields from c and d are null. Does PROGRESS implement outer joins in an unusual manner?
You might want to figure out what the c.n and d.n values are. Try something like this to figure out where your starting point is.
SELECT c.n, d.n, count(*)
FROM a
JOIN b
on a.id = b.id
LEFT JOIN c
on a.id = c.id
LEFT JOIN d
on b.code=d.code
JOIN e
on a.n = e.n
WHERE
a.zone = 10
group by c.n, d.n
Then you can adjust your query based on the result

mysql query to three tables, want to use JOIN instead subquery

I want to use join instead subquery to find the trade id not exist on trade_log filtered by ip and current date for mysql syntax below.
SELECT plug.id as a,
plug.url as b,
trade.id as c
FROM plug, trade
WHERE trade.id = plug.trade_id
AND trade.id NOT IN (SELECT trade_log.trade_id
FROM trade_log
WHERE trade_log.ip = '".$ip."'
AND trade_log.log_date = CURDATE())
AND trade.status = 1
AND plug.status = 1
ORDER BY plug.weight DESC
LIMIT 1
Please help me...
Use:
SELECT p.id as a,
p.url as b,
t.id as c
FROM PLUG p
JOIN TRADE t ON t.id = p.trade_id
AND t.status = 1
LEFT JOIN TRADE_LOG tl ON tl.trade_id = t.id
AND tl.ip = mysql_real_escape_string($ip)
AND tl.log_date = CURDATE()
WHERE p.status = 1
AND tl.ip IS NULL
ORDER BY p.weight DESC
LIMIT 1
Same as OMG Ponies:
SELECT p.id as a,
p.url as b,
t.id as c
FROM plug p
INNER JOIN trade t ON (t.id = p.trade_id AND t.status = 1)
LEFT JOIN trade_log l ON (l.trade_id = t.id AND l.ip = '".$ip."' AND l.log_date = CURDATE())
WHERE p.status = 1 AND l.trade_id IS NULL
ORDER BY p.weight DESC
LIMIT 1