Table:
id | name | country
---------------------
1 | abc | India
2 | abc | America
3 | abc | USA
4 | xyz | India
5 | xyz | America
6 | xyz | USA
QUERY tried so far:
SELECT `id`,
if(`country` = 'India',count(id),0) as object1,
if(`country` = 'America', count(id),0) as object2,
if(`country` = 'USA',count(id),0) as object3
FROM `table`
the above gives me output like this:
id | name | object1 | object2 | object3
---------------------------------------------
1 | India | 6 | 0 | 0
I want output like :
id | name | object1 | object2 | object3
---------------------------------------------
1 | India | 1 | 1 | 1
1 | America | 1 | 1 | 1
1 | USA | 1 | 1 | 1
Please someone help me out to get this output.
I think you want conditional aggregation, but it is unclear what the objects are. Based on the data, I might think:
SELECT country as name,
sum(name = 'abc') as abc,
sum(name = 'xyz') as xyz
FROM `table`
group by country;
Try this:
SELECT `id`,`country`, count(`country`) as 'CountOfCountry'
FROM `table`
GROUP by id,Country
That will give you a count of each unique country, all grouped.
This is assuming that what you are calling "objects" is really the count per country.
I am not quite sure what the third column should be because you don't have the sample data to support it. But how about the following (SQL Fiddle):
SELECT country,
SUM(CASE WHEN name = 'abc' THEN 1 ELSE 0 END) AS object1,
SUM(CASE WHEN name = 'xyz' THEN 1 ELSE 0 END) AS object2,
SUM(CASE WHEN name = 'nunya' THEN 1 ELSE 0 END) AS object3
FROM MyTable
GROUP BY country
I wasn't sure if you wanted to return the ID with your query as all the IDs in your sample output are 1, and I'm not sure how that would represent the sample data you gave, but assuming that was a typo. This is what I came up with. Here is the sql fiddle
http://sqlfiddle.com/#!6/b763d/7
select id,country,
(select count(id) from things where country='india') as object1,
(select count(id) from things where country='america') as object2,
(select count(id) from things where country='usa') as object3
from things
Now if you dont want the ID and just want things to be grouped by country then do the following.
select country,
(select count(id) from things where country='india') as object1,
(select count(id) from things where country='america') as object2,
(select count(id) from things where country='usa') as object3
from things
group by country
Related
I have 2 tables.
1st table: duels
| duelId | user1Id | user2Id | gameId | winnerId |
2nd table: usergameprogress
| usergameprogressId | userId | gameId | gameStar |
Given an userId, I would like to get duel count, gameStar, win count for each gameId.
Example return:
| duelCount | duelWinCount | gameStar | gameId |
I have managed to get duelCount, gameStar and gameId given a userId but I couldn't add duelWinCount to my query result. How do I do that ?
My query:
SELECT
COUNT(d1.duelId) AS duelCount,
usergameprogress.gameId, usergameprogress.gameStar
FROM
duels d1
JOIN
usergameprogress ON (usergameprogress.gameId = d1.gameId)
WHERE
d1.user1Id = "gkfurcwsi033qzxg0u2bmj1ekebsklej"
OR d1.user2Id = "gkfurcwsi033qzxg0u2bmj1ekebsklej"
GROUP BY
usergameprogress.gameId
EDIT:
solved thanks to comment use sum instead of count
SELECT sum(case when d1.user1Id = 'gkfurcwsi033qzxg0u2bmj1ekebsklej' OR d1.user2Id="gkfurcwsi033qzxg0u2bmj1ekebsklej" then 1 else 0 end) AS totalDuelCount,sum(case when winnerId="gkfurcwsi033qzxg0u2bmj1ekebsklej" then 1 else 0 end) AS duelWinCount,usergameprogress.gameId,usergameprogress.gameStar FROM duels d1 JOIN usergameprogress ON (usergameprogress.gameId = d1.gameId) GROUP BY usergameprogress.gameId
I have the following table:
Name Product
Bob Car
Bob Apples
Bob Pears
Bob Car
John Apples
John Pears
Whoever has bought a Product Car, I want to keep separate from everyone else. So, I create a flag:
Name Product Flag
Bob Car 1
Bob Apples 0
Bob Pears 0
Bob Car 1
John Apples 0
John Pears 0
But the problem with my flag is that even if I do a where condition and say, show me the consumer WHERE flag !=1, it'll pick Bob. Which is incorrect as Bob owns a car.
I would still like to GROUP by Product.
How do I separate the above table into two groups?
Thanks!
Use below query :-
select name from table where flag!=1
and name not in (select name from table where flag = 1)
group by name
"show me the consumer WHERE flag !=1, it'll pick Bob" that is because you are asking for rows where flag != 1. Instead you'll need something a little more complicated, like:
SELECT DISTINCT Name
FROM tableTable
WHERE Name NOT IN (SELECT Name FROM theTable WHERE Product = 'Car')
alternatively, you can do a LEFT JOIN, which may or may not be faster depending on the amount of data you have and how its values are distributed.
SELECT DISTINCT a.Name
FROM theTable a
LEFT JOIN theTable b ON a.Name = b.Name AND b.Product = 'Car'
WHERE a.Product != 'Car' AND b.Product IS NULL
;
This gets all the rows with products other than cars, and then uses the LEFT JOIN in conjunction with the IS NULL condition to find which did not also have a 'Car' row.
I think you want your table's data displayed, just with "People who bought cars" partitioned (not grouped) separately somehow - this could be done with an ORDER BY OwnsACar clause, for example.
Step 1: Identify the people who have bought cars:
SELECT DISTINCT
Name
FROM
yourTable
WHERE
Product = 'Car'
Step 2: Join on this data to generate a calculated "OwnsACar" column:
SELECT
yourTable.Name,
yourTable.Product,
ISNULL( carowners.Name ) AS OwnsACar
FROM
yourTable
LEFT OUTER JOIN
(
SELECT DISTINCT
Name
FROM
yourTable
WHERE
Product = 'Car'
) AS carowners ON carowners.Name = yourTable.Name
ORDER BY
OwnsACar ASC,
yourTable.Name ASC
You can use these two queries. The additional Flag column is not required.
-- do not have Car
SELECT *
FROM products
WHERE Name not in (SELECT DISTINCT Name
FROM products
WHERE Product='Car');
-- have Car
SELECT *
FROM products
WHERE Name in (SELECT DISTINCT Name
FROM products
WHERE Product='Car');
Illustration:
-- table
SELECT * FROM products;
+------+---------+
| Name | Product |
+------+---------+
| Bob | Car |
| Bob | Apples |
| Bob | Pears |
| Bob | Car |
| John | Apples |
| John | Pears |
+------+---------+
-- query for people that do not have Car
+------+---------+
| Name | Product |
+------+---------+
| John | Apples |
| John | Pears |
+------+---------+
-- query for people having 'Car'
+------+---------+
| Name | Product |
+------+---------+
| Bob | Car |
| Bob | Apples |
| Bob | Pears |
| Bob | Car |
+------+---------+
Try with :
SELECT `t`.`Name`, `t`.`Product`, SUM(`t`.`Flag`) as hasCar
FROM your_table t
GROUP BY `t`.`Name`
HAVING `t`.`hasCar` = 0;
Although you can go without the flag column by going :
SELECT `t`.`Name`, `t`.`Product`, SUM(IF(`t`.`Product` = 'Car', 1, 0)) as hasCar
FROM your_table t
GROUP BY `t`.`Name`
HAVING `t`.`hasCar` = 0;
I have a table with users and countries either UK or US, now a user can appear multiple times with a different country. I need to select a list with unique users with their country either equal to UK, US or BOTH.
This is the approach Im trying but it doesn't appear to be working.
select user,
case
when COUNT(*) <= 1 and count(select where = "UK") = count(*) then "UK"
when COUNT(*) <= 1 and count(select where = "US") = count(*) then "US"
when COUNT(*) <= 1 and count(select where = "US") != count(*) then "BOTH"
END CASE
as country from users;
First time using logic like this in a query so sorry for sounding like a noob.
+------------------------------+-------------+
| user | country |
+------------------------------+-------------+
| John | US |
| Jack | US |
| John | UK |
| Joe | US |
| John | UK |
| Jacky | US |
+------------------------------+-------------+
You could do something like:
SELECT
temp.user,
if(temp.CountryList = "UK,US", "BOTH", temp.CountryList) as country
FROM
(
SELECT
user,
group_concat(DISTINCT country ORDER BY country) as CountryList
FROM USERS
GROUP BY user
) temp
Firstly, I apologize for the terrible wording, but I'm not sure how to describe what I'm doing...
I have a table of computer types (id, type, name), called com_types
id | type | name
1 | 1 | Dell
2 | 4 | HP
In a second table, I have each individual computer, with a column 'type_id' to denote what type of computer it is, called com_assets
id | type_id | is_assigned
1 | 4 | 0
2 | 1 | 1
I'd like to create a view that shows each computer type, and how many we have on hand and in use, and a total, so the outcome would be
id | type | name | on_hand | in_use | total |
1 | 1 | Dell | 0 | 1 | 1 |
2 | 4 | HP | 1 | 0 | 1 |
As you can see, the on_hand, in_use, and total columns are dependent on the type_id and is_assigned column in the second table.
So far I have tried this...
CREATE VIEW test AS
SELECT id, type, name,
( SELECT COUNT(*) FROM com_assets WHERE type_id = id AND is_assigned = '0' ) as on_hand,
( SELECT COUNT(*) FROM com_assets WHERE type_id = id AND is_assigned = '1' ) as in_use,
SUM( on_hand + in_use ) AS total
FROM com_types
But all this returns is one column with all correct values, except the total equals ALL of the computers in the other table. Will I need a trigger to do this instead?
on_hand is the count of assigned = 0, and in_use is the count of assigned = 1. You can count them together, without the correlated subqueries, like this:
SELECT
com_types.id,
com_types.type,
com_types.name,
COUNT(CASE WHEN com_assets.is_assigned = 0 THEN 1 END) AS on_hand,
COUNT(CASE WHEN com_assets.is_assigned = 1 THEN 1 END) AS in_use,
COUNT(*) AS total
FROM com_types
JOIN com_assets ON com_types.id = com_assets.id
GROUP BY
com_types.id,
com_types.type,
com_types.name
I've got table with two columns: name and grade. It looks sth like this:
NAME | GRADE
Adam | 1
Adam | 2
Adam | 2
Adam | 3
Frank | 2
Frank | 1
Now I want create view that will looks like this:
NAME | GRADE 1 | GRADE 2 | GRADE 3
Adam | 1 | 2 | 1
Frank | 1 | 1 | 0
I've wrote this:
SELECT Name,
(SELECT COUNT(Grade)
FROM dbo.Rodzaj
WHERE Grade = '1') as Grade_1,
(SELECT COUNT(Grade)
FROM dbo.Rodzaj
WHERE Grade = '2) as Grade_2,
(SELECT COUNT(Grade)
FROM dbo.Rodzaj
WHERE Grade = '3') as Grade_3
FROM dbo.Rodzaj
GROUP BY Name
but it doesn't work...
I would appreciate any help
What you are looking for is called a "pivot table" and it is done with a chain of CASE statements which apply a 1 or 0 for each condition, then SUM() up the ones and zeros to retrieve a count.
SELECT
NAME,
SUM(CASE WHEN GRADE = 1 THEN 1 ELSE 0 END) AS GRADE1,
SUM(CASE WHEN GRADE = 2 THEN 1 ELSE 0 END) AS GRADE2,
SUM(CASE WHEN GRADE = 3 THEN 1 ELSE 0 END) AS GRADE3
FROM Rodzaj
GROUP BY NAME
Note that if you need this to have a dynamic number of columns, you will have to construct the query using a scripting language and a loop. (Or a loop inside a stored procedure)