sql query to perform for each unique identifier - mysql

So I have a table like this:
________________________________________
phone_number | phone_vendor | status
67834 | A | OPEN
23836 | B | OPEN
87483 | C | CLOSED
72377 | A | OPEN
63637 | B | OPEN
I need to find the count of phone_numbers of each unique phone_vendor in OPEN status, something like:
A | 2
B | 2
C | 0
using group by I don't get the vendors whose OPEN count is already exhausted (as C in above example)
What could be a suitable query?
Also, I can't use CASE as there will be multiple vendors.
Query attempt:
SELECT status, count(phone_number) AS count
FROM phone_number_table
WHERE status = 'OPEN'
GROUP BY phone_vendor, status

Try this:
SELECT SUM(CASE WHEN status = 'OPEN' THEN 1 ELSE 0 END) AS count, phone_vendor
FROM yourtable
Group by phone_vendor
SQL Demo: http://sqlfiddle.com/#!9/17e753/4

You could check for status and sum
select phone_vendor, sum(case status when 'OPEN' then 1 else 0 end) my_count
from my_table
group by phone_vendor

Related

Select group multiple records by specific condition

I have table:
+----+-------+-------------+
| id | code | value_check |
| 1 | p-01 | OK |
| 2 | p-01 | NOT OK |
| 3 | p-01 | OK |
| 4 | p-02 | OK |
| 5 | p-02 | OK |
| 6 | p-02 | OK |
+----+-------+-------------+
How can I select record which having 'OK' group by code,but if there is one or more 'NOT OK' on value_check then don't need to select
expected result:
code
p-02
i have tried my query can get the result but its very slow
this is my query :
SELECT code FROM table
WHERE code
NOT IN (SELECT code FROM table
WHERE value_check = 'NOT OK' GROUP BY code)
GROUP BY code
any other solution?
Check whether the total count is equal to the count of rows having value as OK using HAVING clause.
Query
select `code` from `your_table_name`
group by `code`
having count(*) = sum(`value_check` = 'OK');
Find a demo here
Try below with conditional aggregation
select code from table
group by code
having sum(case when value_check='NOT OK' then 1 else 0 end)=0
You can try it also with correlated subquery:
demo
SELECT distinct code FROM cte1 a
WHERE NOT exists (SELECT 1 FROM cte1 b where a.code=b.code and val = 'NOT OK')
SELECT DISTINCT x.code
FROM my_table x
LEFT
JOIN my_table y
ON y.code = x.code
AND y.value_check = 'not ok'
WHERE x.value_check = 'ok'
AND y.id IS NULL

SQL query to get all records in a certain status within a foreign key

I have a fairly big table (10,000+ records) that looks more or less like this:
| id | name | contract_no | status |
|----|-------|-------------|--------|
| 1 | name1 | 1022 | A |
| 2 | name2 | 1856 | B |
| 3 | name3 | 1322 | C |
| 4 | name4 | 1322 | C |
| 5 | name5 | 1322 | D |
contract_no is a foreign key which of course can appear in several records and each record will have a status of either A, B, C, D or E.
What I want is to get a list of all the contract numbers, where ALL the records referencing that contract are in status C, D, E, or a mix of those, but if any of the records are in status A or B, omit that contract number.
Is it possible to do this using a SQL query? Or should I better export the data and try to run this analysis using another language like Python or R?
Post aggregate filtering should do the trick
SELECT contract_no FROM t
GROUP BY contract_no
HAVING SUM(status='A')=0
AND SUM(status='B')=0
You can use group by with having to get such contract numbers.
select contract_number
from yourtable
group by contract_number
having count(distinct case when status in ('C','D','E') then status end) >= 1
and count(case when status = 'A' then 1 end) = 0
and count(case when status = 'B' then 1 end) = 0
Not that elegant as the other two answers, but more expressive:
SELECT DISTINCT contract_no
FROM the_table t1
WHERE NOT EXISTS (
SELECT *
FROM the_table t2
WHERE t2.contract_no = t1.contract_no
AND t2.status IN ('A', 'B')
)
Or
SELECT DISTINCT contract_no
FROM the_table
WHERE contract_no NOT IN (
SELECT contract_no
FROM the_table
AND status IN ('A', 'B')
)

Rows to columns in mysql

I'm doing the select:
select id,
status,
count(status) as qtd
from user
group by id, status;
The return is:
id | status | qtd
1 YES 5
1 NO 3
2 YES 3
2 NO 1
I want this:
id | YES | NO
1 5 3
2 3 1
Thanks.
NOTE:
you can use case logic to do what you want.. basically you want to pivot the results and to pivot them you have to use aggregates with conditionals to fake a pivot table since mysql doesn't have a way to accomplish that
QUERY:
SELECT
id,
SUM(CASE status WHEN 'Yes' THEN 1 ELSE 0 END) as 'YES',
SUM(CASE status WHEN 'No' THEN 1 ELSE 0 END) as 'NO'
FROM user
GROUP BY id;
DEMO
OUTPUT:
+----+-----+----+
| id | YES | NO |
+----+-----+----+
| 1 | 5 | 3 |
| 2 | 3 | 1 |
+----+-----+----+
You can do so,using expression in sum() like sum(status ='Yes') will result as boolean (0/1) and thus you can have your count based on your criteria you provide in sum function
select id,
sum(status ='Yes') as `YES`,
sum(status ='No') as `NO`
from user
group by id;

combining multiple different sql into one

cusID | Name | status | Date
---------------------------------
1 | AA | 0 | 2013-01-25
2 | BB | 1 | 2013-01-23
3 | CC | 1 | 2013-01-20
SELECT COUNT(cusID) FROM customer WHERE STATUS=0;
SELECT COUNT(cusID) FROM customer WHERE STATUS=1;
Is there a way of combing such two sql and return the results as one. Because want to avoid calling to DB everytime. I tried UNION of two statments, but only showing one result.
This is the shortest possible solution in MySQL.
SELECT SUM(status = 1) totalActive,
SUM(status = 0) totalInactive
FROM tableName
SQLFiddle Demo
and this is the CASE version
SELECT SUM(CASE WHEN status = 1 THEN 1 ELSE 0 END) totalActive,
SUM(CASE WHEN status = 0 THEN 1 ELSE 0 END) totalInactive
FROM tableName
SQLFiddle Demo

Exclude duplicate rows in query result

I want to count the number of records in database from more than two tables that are joined.
For example I have a table like this.
table
jobd + name
1 | jobA
2 | jobB
tableA
imgeid + orderid + jobid
1 | 1 | 1
2 | 2 | 1
3 | 3 | 1
4 | 4 | 1 (this order is not yet started)
tableB
taskid + orderid + task + status
1 | 1 | 1 | UPDATED
2 | 1 | 1 | UPDATED
3 | 1 | 1 | COMPLETED
4 | 2 | 2 | SAVED
5 | 3 | 3 | COMPLETED
My problem here is that when I count base on status (# tableB) my query results both the UPDATED which has the same orderid.
This is my sample query that same with the one I'm working.
SELECT t.name
COUNT(CASE WHEN tb.task = 1 AND tb.status <> 'COMPLETED' THEN tb.status ELSE NULL END) inprogress,
COUNT(CASE WHEN tb.task = 1 AND tb.status = 'COMPLETED' THEN tb.status ELSE NULL END) completed
FROM tableA ta
LEFT JOIN tableB tb
ON tb.orderid = ta.orderid
LEFT JOIN table t
ON t.jobid = ta.jobid
GROUP BY t.jobid;
My results something like
name + inprogress + completed
jobA | 2 | 1
The inprogress results must only be 1 because it has the same orderid. The reason why it has two UPDATED because this table is HISTORICAL. I don't know how can get the distinct orderid in tableB so it will only results to 1.
The main point here is that I can count the total orders which status is in progress, completed and not started per job.
I hope my question is clear. If you have other way, please let me know. Thanks
Can't you use a Count distinct? Here's a link, see nearer the bottom of the page, it will only the unique field you specify: w3schools.com/sql/sql_func_count.asp
SELECT t.name
COUNT(DISTINCT tb.orderid CASE WHEN tb.task = 1 AND tb.status 'COMPLETED' THEN tb.status
ELSE NULL END) inprogress,
COUNT(DISTINCT tb.orderid CASE WHEN tb.task = 1 AND tb.status = 'COMPLETED' THEN tb.status
ELSE NULL END) completed