The scenario is I have a column named "States" in a table, States can be 0,1,2,3 or 4. What I want to do is get a count of each state using WHERE State = in a single query.
The main purpose is I want to show the count of records (identified by their state). Like this, 20 records have State 0 etc.
Is this possible? If yes, then how can I achieve this?
Edit: I know about Count. Here's what I have tried:
SELECT State, Date_Created, (SELECT COUNT(Id) FROM [ECOS].[eco].[tb_projects_details] WHERE State=1) as State_One, (SELECT COUNT(Id) FROM [ECOS].[eco].[tb_projects_details] WHERE State=2) as State_Two, (SELECT COUNT(Id) FROM [ECOS].[eco].[tb_projects_details] WHERE State=0) as State_Zero, (SELECT COUNT(Id) FROM [ECOS].[eco].[tb_projects_details] WHERE State=4) as State_Four FROM [ECOS].[eco].[tb_projects_details] WHERE Date_Created < dateadd(week,-3,getdate());
If I understand it correctly, you want to group and count:
SELECT mt.States, COUNT(*) total
FROM my_table mt
GROUP BY mt.States
To generate a list of values and their counts you can do this:
SELECT State, COUNT(*) AS C
FROM mytable
GROUP BY State
To generate one row that contains value counts as columns you can do this:
SELECT
COUNT(CASE State WHEN 0 THEN 1 ELSE NULL END) AS State_0_Count,
COUNT(CASE State WHEN 1 THEN 1 ELSE NULL END) AS State_1_Count,
COUNT(CASE State WHEN 2 THEN 1 ELSE NULL END) AS State_2_Count,
COUNT(CASE State WHEN 3 THEN 1 ELSE NULL END) AS State_3_Count,
COUNT(CASE State WHEN 4 THEN 1 ELSE NULL END) AS State_4_Count
FROM [...]
WHERE [...]
It will be very easy if you use group by clause after where condition. Then you will get the number of each state very easily.
SELECT state, count(*)
FROM table_name
GROUP BY state
Next time read a sql for beginers book first.
Select state, count(*)
from table
group by state
Related
I'm working with Yii2 and using ActiveRecords. I am trying find ethnic distribution in a department. I have a query that groups the staff into their tribes and further groups them according to gender and returns the total count in each case.
The end result should look similar to this photo:
The ethnic subtotal is given by adding all the totals of all the tribes in the department. So far I have all the totals for all the tribes in each department. How can I add these totals to get the ethnic subtotal?
My code:
$query = StaffEmploymentListView::find()
->select([
'DEPT_NAME',
'TRIBE_NAME',
"COUNT(CASE WHEN GENDER='MALE' THEN 1 END) AS MALE_COUNT",
"COUNT(CASE WHEN GENDER='FEMALE' THEN 1 END) AS FEMALE_COUNT",
"COUNT(TRIBE_NAME) AS TRIBE_COUNT",
])
->groupBy(['DEPT_NAME','TRIBE_NAME']);
Raw SQL answers are also welcome.
I am not familiar with yii, but generally speaking you can just use + to add values, so your selection criteria would be something like count(...) + count(...) will select the sum of those two counts.
select t.DEPT_NAME,
SUM(CASE WHEN GENDER = 'MALE' OR GENDER = 'FEMALE' THEN 1 END) as SUM,
tt.MALE_COUNT,
tt.FEMALE_COUNT,
tt.TRIBE_COUNT,
tt.TRIBE_NAME from 'StaffEmploymentListView' t
left join (
select DEPT_NAME,
TRIBE_NAME,
SUM(CASE WHEN GENDER = 'MALE' THEN 1 END) as MALE_COUNT,
SUM(CASE WHEN GENDER = 'FEMALE' THEN 1 END) as FEMALE_COUNT,
count(TRIBE_NAME) as TRIBE_COUNT
from 'StaffEmploymentListView' t
group by DEPT_NAME, TRIBE_NAME) tt on t.DEPT_NAME = tt.DEPT_NAME group by t.DEPT_NAME, tt.MALE_COUNT, tt.FEMALE_COUNT, tt.TRIBE_COUNT, tt.TRIBE_NAME;
This maybe can help you, i plat with postgresql
I have two tables one is "invoices" and other is "invoice_items".so i want to generate report using these two tables.
This should do the trick...please have a look on CASE WHEN
select i.Date, i.No,sum(CASE WHEN t.VAT<>'no' THEN
amount ELSE 0 END) as Excluding_VAT,
sum(t.amt_vat)as vatamount,
sum(CASE WHEN t.VAT='no' THEN amount ELSE 0 END) as NonVat,
sum(t.amt_vat+t.amount)as totamt
from a i join b t on i.ID=t.ID
where i.Date between '1991-11-18' and '1995-11-19'
group by i.ID,i.No,i.Date
this is for Sale_Value_Excluding_VAT
SELECT SUM(amount) FROM (select amount from invoice_items join invoices on invoices.invoiceid=invoice_items.invoiceid
where includevat=TRUE) AS T
When i select data only show first lot data . but i need all lot data.
Here is my query:
SELECT lot,
(select count(pass) FROM pass_fail_result where pass=0) toatl_fail,
(select count(pass) FROM pass_fail_result where pass=1) toatl_pass FROM pass_fail_result group by lot;
I want to show all pass result like pass=10 and fail=2
The easiest way to do this is via conditional aggregation, where we count or sum CASE expressions which target the failing or passing records:
SELECT
lot,
COUNT(CASE WHEN pass = 0 THEN 1 END) AS toatl_fail,
COUNT(CASE WHEN pass = 1 THEN 1 END) AS toatl_pass
FROM pass_fail_result
GROUP BY
lot;
I have this table :
id idm date_play
1 5 2017-08-23 12:12:12
2 5 2017-08-23 12:12:12
3 6 2017-08-23 12:14:13
I want to identify if user has more then one insert in the same second. In the case describe I want to get the user id that is 5.
I tried like this :
SELECT `idm`, MAX(`s`) `conseq` FROM
(
SELECT
#s := IF(#u = `idm` AND (UNIX_TIMESTAMP(`date_play`) - #pt) BETWEEN 1 AND 100000, #s + 1, 0) s,
#u := `idm` `idm`,
#pt := UNIX_TIMESTAMP(`date_play`) pt
FROM table
WHERE date_play >= '2017-08-23 00:00:00'
AND date_play <= '2017-08-23 23:59:59'
ORDER BY `date_play`
) AS t
GROUP BY `idm`
Can you help me please ? Thx in advance and sorry for my english.
Assuming your dates are accurate down to the second level, you can do this with a single aggregation:
select idm
from t
group by idm
having count(*) > count(distinct date_play);
If date_play has fractional seconds, then you would need to remove those (say by converting to a string).
If you want the play dates where there are duplicates:
select idm, date_play
from t
group by idm, date_play
having count(*) >= 2;
Or, for just the idms, you could use select distinct with group by:
select distinct idm
from t
group by idm, date_play
having count(*) >= 2;
(I only mention this because this is the only type of problem that I know of where using select distinct with group by makes sense.)
If you want all the rows that are duplicated, I would go for exists instead:
select t.*
from t
where exists (select 1
from t t2
where t2.idm = t.idm and t2.date_play = t.date_play and
t2.id <> t.id
);
This should have reasonable performance with an index on (idm, date_play, id).
If your table is called mytable, the following should work:
SELECT t.`idm`
FROM mytable t INNER JOIN mytable t2
ON t.`idm`=t2.`idm` AND t.`date_play`=t2.`date_play` AND t.`id`!=t2.`id`
GROUP BY t.`idm`
Basically we join the table with itself, pairing records that have the same idm and date_play, but not the same id. This will have the effect of matching up any two records with the same user and datetime. We then group results by user so you don't get the same user id listed multiple times.
Edit:
Gordon Linoff and tadman's suggestions led me to this probably much more efficient query (credit to them)
SELECT t.`idm`
FROM mytable t
GROUP BY t.`date_play`
HAVING COUNT(t.`id`)>1
I have a table with a field called type, where 3 various rows are possible: 1, 2 and 3.
Now, I don't care about 3 at all. I need to count how many rows there are with type = 1 and with type = 2. I am doing this with 2 queries, like this:
Query1: SELECT COUNT(id) as count FROM users WHERE type='1'
Query2: SELECT COUNT(id) as count FROM users WHERE type='2'
Can I do this with only 1 single query? If so, should I, or not? How would the query look?
SELECT type,
COUNT(id) AS count
FROM users
WHERE type IN ('1','2')
GROUP BY type
SELECT type, COUNT(id) AS count
FROM users
GROUP BY type
HAVING type < 3
SELECT sum(case when type = '1' then 1 else 0 end) as count_for_one,
sum(case when type = '2' then 1 else 0 end) as count_for_tow
FROM users
WHERE type IN ('1','2')
If you want separate numbers,
SELECT SUM(IF(type='1', 1, 0)), SUM(IF(type='2', 1, 0))
FROM users WHERE type IN ('1', '2')