sql: why does query repeat values when using 'GROUP CONCAT' + 'GROUP BY'? - sql

The Query:
SELECT MemberId, a.MemberName, GROUP_CONCAT(FruitName) FROM a LEFT JOIN b ON
a.MemberName = b.MemberName GROUP BY a.MemberName
Table a
MemberID MemberName
-------------- ----------
1 Al
1 Al
3 A2
Table b
MemberName FruitName
--------------- --------------
Al Apple
Al Mango
A2 Cherry
Resulting Output from above query:
MemberId MemberName GROUP_CONCAT(FruitName)
3 A2 Cherry
1 A1 Apple,Apple,Mango,Mango
The actual tables I am using have 10 columns apiece so just storing everything in one table is not a workaround. That said, how can I change the query to only return 'Apple,Mango' for MemberName?

Add the keyword DISTINCT to the grouped column:
GROUP_CONCAT(DISTINCT FruitName)

try
GROUP_CONCAT(Distinct FruitName)

SELECT MemberId, a.MemberName, GROUP_CONCAT(DISTINCT FruitName)
FROM a
LEFT JOIN
b
ON a.MemberName = b.MemberName
GROUP BY
a.MemberName

Related

Select all items having silmutaneously 2different values at the same column

I want to run an sql query and find all the books that have type="adventure" AND type="drama".
AND does not allow searching at the same time 2 different values of the same column.
My tables are like this
Books
Bid Bname Author
1 Sql loren
2 Monster Mike
3 Minnie Michel
----------
Copies
Cid Bid Type
1 1 Science
2 1 Teaching
3 2 Adventure
4 3 Romance
5 3 Drama
6 3 Adventure
The result I want:
Bid Title
3 Minnie
The tables can't change
There are several ways to do it, here is one using two exists conditions. Bottom line is that you have to check copies table twice.
SELECT * FROM books b
WHERE EXISTS
(
SELECT * FROM copies c1
WHERE b.bid = c1.bid
AND c1.type='adventure'
)
AND EXISTS
(
SELECT * FROM copies c2
WHERE b.bid = c2.bid
AND c2.type='drama'
)
You can achieve with JOIN, here is the DEMO. And you can use EXISTS as per #NenadZivkovic answer.
select
b.Bid,
Bname as Title
from books b
join Copies c
on b.Bid = c.Bid
and c.Type ='Drama'
join Copies c1
on c.Bid = c1.Bid
and c1.Type = 'Adventure'
group by
b.Bid,
Bname
order by
b.Bid

Trying to count particular column from three different tables

Master table
SerNo HospitalId CityId
1 1 1
2 1 1
3 2 2
4 3 2
5 1 1
HospitalMaster
HospitalId HospitalName
1 ABC
2 XYZ
CityMaster
CityId City
1 Delhi
2 Bombay
Result
I need something like this
City TotalHospital
Delhi 1
Bombay 2
I tried joining the tables but I keep getting the total rows of the columns and not of the hospitals.
Thank you.
Left join the city master table to a subquery which finds the hospital counts for each city. Note carefully that we only count distinct hospitals, because a hospital city relationship may appear more than once in the master table.
SELECT t1.City, COALESCE(t2.cnt, 0) AS TotalHospital
FROM CityMaster t1
LEFT JOIN
(
SELECT CityId, COUNT(DISTINCT HospitalId) cnt
FROM Master
GROUP BY CityID
) t2
ON t1.CityId = t2.CityId;
Demo
Try this:
SELECT C.City,COUNT(DISTINCT HospitalID)TotalHospital
FROM CityMaster C
JOIN Master_table M ON M.CityId=C.CityId
GROUP BY C.City
You could apply join
select M.City,count(distinct M.HospitalId) from CityMaster C inner join Master M ON C.CityId = M.CityId
group by M.City
You can do it with using JOIN
Just replace #city, #hospital, #table with your table names.
select C.City,T.CityId from #city C,#hosp H,#table T WHERE T.CityId = C.CityId AND T.HospitalId = H.HospitalId Group by C.City,T.CityId
As we need city name along with count, we can get by join city master and master tables.
select max(C.cityname), count(distinct M.HospitalId)
from CityMaster C
inner join Master M
on C.Cityid = M.CityId
group by M.cityid

Select all categories with COUNT of sub-categories

I need to select all categories with count of its sub-categories.
Assume here are my tables:
categories
id | title
----------
1 | colors
2 | animals
3 | plants
sub_categories
id | category_id | title | confirmed
------------------------------------
1 1 red 1
2 1 blue 1
3 1 pink 1
4 2 cat 1
5 2 tiger 0
6 2 lion 0
What I want is :
id | title | count
------------------
1 colors 3
2 animals 1
3 plants 0
What I have tried so far:
SELECT c.id, c.title, count(s.category_id) as count from categories c
LEFT JOIN sub_categories s on c.id = s.category_id
WHERE c.confirmed = 't' AND s.confirmed='t'
GROUP BY c.id, c.title
ORDER BY count DESC
The only problem with this query is that this query does not show categories with 0 sub categories!
You also can check that on SqlFiddle
Any help would be great appreciated.
The reason you don't get rows with zero counts is that WHERE clause checks s.confirmed to be t, thus eliminating rows with NULLs from the outer join result.
Move s.confirmed check into join expression to fix this problem:
SELECT c.id, c.title, count(s.category_id) as count from categories c
LEFT JOIN sub_categories s on c.id = s.category_id AND s.confirmed='t'
WHERE c.confirmed = 't'
GROUP BY c.id, c.title
ORDER BY count DESC
Adding Sql Fiddle: http://sqlfiddle.com/#!17/83add/13
I think you can try this too (it evidence what column(s) you are really grouping by):
SELECT c.id, c.title, RC
from categories c
LEFT JOIN (SELECT category_id, COUNT(*) AS RC
FROM sub_categories
WHERE confirmed= 't'
GROUP BY category_id) s on c.id = s.category_id
WHERE c.confirmed = 't'
ORDER BY RC DESC

City names as column title

I have two tables.
Food Table
--------------------------
ID CityID FoodName
--------------------------
1 1 FoodA
2 1 FoodB
3 1 FoodC
4 2 FoodW
5 2 FoodX
6 2 FoodY
7 2 FoodZ
City Table
--------------------------
ID CityName
--------------------------
1 Memphis
2 Nashville
3 Chattanooga
So How can I use CityName s as Column title and list the food in that city.
--------------------------------------
Memphis Nashville Chattanooga
--------------------------------------
FoodA FoodW
FoodB FoodX
FoodC FoodY
FoodZ
I'm pretty sure on that I have to use pivot but I couldn't find a good solution yet.
This is what I've achieved so far.
SELECT *
FROM (
SELECT *
FROM Food F
INNER JOIN City C ON C.ID = F.CityID
) DataTable D
PIVOT(F.FoodName FOR C.CityName IN (
[Memphis]
,[Nashville]
,[Chattanooga]
)) PivotTable
you can use this query to get your output. Actually you did some mistakes to setup the pivot query.
select Memphis,Nashville,Chattanooga
from
(
select f.ID,c.CityName,f.FoodName
from Food f
inner join City c
on f.CityID=c.id
)result
pivot
(
max(FoodName)
for CityName in(Memphis,Nashville,Chattanooga)
) as pvt
The PIVOT operator uses the columns from the data table that are not in the PIVOT definition as GROUP anchor.
That mean that two values will be in the same row of a PIVOT table when they have the same value in the columns of data table that are neither the aggregated one or the pivoted one.
The OP data don't have this value so a new partitioned id is generated.
SELECT Memphis, Nashville, Chattanooga
FROM (SELECT c.CityName, f.FoodName
, FoodID = Row_Number() OVER (PARTITION BY c.ID ORDER BY FoodName)
FROM Food f
INNER JOIN City c ON f.CityID = c.id) d
PIVOT
(MAX(FoodName) FOR CityName IN (Memphis,Nashville,Chattanooga)) pvt

Using table joins to put seq no to the grouped items in the select SQL Query result

can any one help to solve this issue in SQL SERVER 2008. I want to put seq numbering to the grouped items in the select query result.
select a.grade, a.name, a.age, seqno
from tab A join tab B on A.id = B.id
[group based on Grade column]
The result should show as shown below.
SeqNo Grade Name Age
----- ----- ---- ---
1 A abc 23
2 A xyz 7
1 B dfg 34
2 B sxd 23
3 B vvv 56
In the below query, how i can join the second table and using a "join'
SELECT ROW_NUMBER() OVER ( PARTITION BY [a.Grade] ORDER BY [a.Name]) AS 'SeqNo',
[a.Grade], [a.Name], [a.Age]
FROM Employee a WITH (NOLOCK)
ORDER BY [a.Grade],[a.Name]