MySQL SELECT FROM WHERE COUNT - php

Hi im looking for an MySQL Select that returns only that rows with doubled entries in column xxx
example:
+------+------+------------+--------------------+
| id | name | work_date | daily_typing_pages |
+------+------+------------+--------------------+
| 1 | John | 2007-01-24 | 250 |
| 2 | Ram | 2007-05-27 | 220 |
| 3 | Jack | 2007-05-06 | 170 |
| 4 | Jack | 2007-04-06 | 100 |
| 5 | Jill | 2007-04-06 | 220 |
| 6 | Zara | 2007-06-06 | 300 |
| 7 | Zara | 2007-02-06 | 350 |
+------+------+------------+--------------------+
Got This Table and i want to read out all entries thats name is listed more than once,
my Query is not working cause it just shows entries with two times the name just once
SELECT id, name, COUNT(name) AS count
FROM table_xy
having count(name) > 1;
what i want to have returned:
+------+------+------------+
| id | name | count |
+------+------+------------+
| 3 | Jack | 2 |
| 4 | Jack | 2 |
| 6 | Zara | 2 |
| 7 | Zara | 2 |
+------+------+------------+
Is there a way to get that?

You could use a subquery for your group by:
SELECT x.id, y.name, y.count
FROM table_xy AS x
INNER JOIN
( SELECT Name, COUNT(*) AS count
FROM table_xy
GROUP BY Name
HAVING COUNT(*) > 1
) AS y
ON y.Name = x.Name;
Alternatively you could use a self join with distinct if you don't need the count:
SELECT DISTINCT x.ID, x.Name
FROM table_xy AS x
INNER JOIN table_xy AS y
ON x.Name = y.Name
AND x.ID != y.ID;
Or a self join with GROUP BY if you do need the count:
SELECT x.ID, x.Name, COUNT(y.ID) + 1 AS count
FROM table_xy AS x
INNER JOIN table_xy AS y
ON x.Name = y.Name
AND x.ID != y.ID
GROUP BY x.ID, x.Name;
Examples on SQL Fiddle

try this...
SELECT x.ID, x.Name, COUNT(y.ID) + 1 AS count
FROM table_xy AS x
INNER JOIN table_xy AS y
ON x.Name = y.Name
AND x.ID != y.ID
GROUP BY x.ID, x.Name;

Related

Insert `COUNT(*)` based on separate table

In MySQL is it possible to select columns from one table while also creating a column for COUNT(*) based on other tables? That way a summary of the results from all tables can be returned. This might be a bit confusing to explain in words so I made some sample tables instead:
events_tbl
----------------------------
id | eventname
1 | Anime Festival
2 | Food Festival
----------------------------
booths_tbl
-------------------------
id | boothname
1 | Walmart
2 | Pizza Hut
3 | Nike
4 | North Face
-------------------------
participants_tbl
-----------------------------
id | participantname
1 | John
2 | Mike
3 | Rambo
4 | Minnie
-----------------------------
event_booths_tbl
--------------------------------
event_id | booth_id
1 | 1
1 | 2
1 | 5
2 | 3
2 | 4
--------------------------------
event_participants_tbl
-------------------------------------
event_id | booth_id
1 | 1
1 | 2
1 | 3
1 | 4
-------------------------------------
Is there a way to get results like this in MySQL:
summary_tbl
------------------------------------------------------------------------
id | eventname | booth_count | participant_count
1 | Anime Festival | 3 | 4
2 | Food Festival | 2 | 0
------------------------------------------------------------------------
The event_participants_tbl should contain participant_id instead of booth_id.
Its irrelevant otherwise.
Your MySQL query would be like this :
select
et.id,
et.eventname,
count(distinct ebt.booth_id) as booth_count,
count(distinct ept.participant_id) as participant_count
from
event_booths_tbl ebt
left join events_tbl et on et.id=ebt.event_id
left join event_participants_tbl ept on ept.event_id=ebt.event_id
group by et.event_id;
Join with subqueries that count in each table:
SELECT e.id, e.event_name,
IFNULL(b.booth_count, 0) AS booth_count,
IFNULL(p.participant_count, 0) AS participant_count
FROM events_table AS e
LEFT JOIN (SELECT event_id, COUNT(*) AS booth_count
FROM event_booths_table
GROUP BY event_id) AS b ON e.id = b.event_id
LEFT JOIN (SELECT event_id, COUNT(*) AS participant_count
FROM event_participants_table
GROUP BY event_id) AS p ON e.id = p.event_id
Try this :
select event.id,
event.name,
count(distinct eventBooth.booth_id),
count(distinct eventParitcipant.booth_id)
from events_tbl event
LEFT JOIN event_booths_tbl eventBooth on eventBooth.event_id=event.id
LEFT JOIN event_participants_tbl eventParitcipant
on eventParitcipant.event_id=event.id
group by event.id

Mysql Remove Duplicates on Left Join 3 Tables using id

I have the following tables
hobbies
+----+-------------+---------------+
| id | employeeid | hobby_name |
+----+-------------+---------------+
| 1 | 123 | cooking |
| 2 | 123 | painting |
| 3 | 124 | dancing |
+----+-------------+---------------+
nonacad_recog
+----+-------------+---------------+
| id | employeeid | recog_name |
+----+-------------+---------------+
| 1 | 123 | Award1 |
| 2 | 123 | Award2 |
| 3 | 124 | Award3 |
+----+-------------+---------------+
org_membership
+----+-------------+---------------+
| id | employeeid | recog_name |
+----+-------------+---------------+
| 1 | 123 | Boyscout |
| 2 | 124 | Girlscout |
+----+-------------+---------------+
This is the query I used:
SELECT h.hobby_name,r.recog_name,o.org_name
FROM hobbies as h
JOIN nonacad_recog as r ON (h.employeeid=r.employeeid)
JOIN org_membership as o ON (r.employeeid=o.employeeid)
WHERE h.employeeid='123'
I am getting duplicate outputs:
+----+-------------+---------------------+
| hobby_name | recog_name | org_name |
+----+-------------+---------------------+
| cooking | Award1 | Boyscout |
| cooking | Award2 | Boyscout |
| painting| Award1 | Boyscout |
| painting| Award2 | Boyscout |
+----+-------------+---------------------+
What I want as an output is like this: with no duplicates
+----+-------------+---------------------+
| hobby_name | recog_name | org_name |
+----+-------------+---------------------+
| cooking | Award1 | Boyscout |
| painting| Award2 | NULL |
+----+-------------+---------------------+
also giving a null to the other columns/rows if there is nothing to return.
I might have missed out some things.
Is this possible to achieve using mysql queries?
Any solution to this?
If I get the correct table, it will be easy for me to
mysqli_fetch assoc the results and display it on a table using PHP.
The problem is that in the desired output you want to relate rows in your tables by non-existent column, which is a row number.
You can technically do it like this
SELECT MAX(CASE WHEN source = 1 THEN name END) hobby_name,
MAX(CASE WHEN source = 2 THEN name END) recog_name,
MAX(CASE WHEN source = 3 THEN name END) org_name
FROM
(
SELECT 1 source, id, hobby_name name, #n1 := #n1 + 1 rnum
FROM hobbies CROSS JOIN (SELECT #n1 := 0) i
WHERE employeeid = 123
UNION ALL
SELECT 2 source, id, recog_name, #n2 := #n2 + 1 rnum
FROM nonacad_recog CROSS JOIN (SELECT #n2 := 0) i
WHERE employeeid = 123
UNION ALL
SELECT 3 source, id, org_name, #n3 := #n3 + 1 rnum
FROM org_membership CROSS JOIN (SELECT #n3 := 0) i
WHERE employeeid = 123
ORDER BY source, id
) q
GROUP BY rnum
Output:
| HOBBY_NAME | RECOG_NAME | ORG_NAME |
|------------|------------|----------|
| cooking | Award1 | Boyscout |
| painting | Award2 | (null) |
Here is SQLFiddle demo
Here is an alternative solution. You pack all values as delimited strings with GROUP_CONCAT()
SELECT GROUP_CONCAT(DISTINCT hobby_name ORDER BY h.id) hobby_name,
GROUP_CONCAT(DISTINCT recog_name ORDER BY r.id) recog_name,
GROUP_CONCAT(DISTINCT org_name ORDER BY o.id) org_name
FROM
(
SELECT 123 employeeid
) e LEFT JOIN hobbies h
ON e.employeeid = h.employeeid
LEFT JOIN nonacad_recog r
ON e.employeeid = r.employeeid
LEFT JOIN org_membership o
ON e.employeeid = o.employeeid;
Output:
| HOBBY_NAME | RECOG_NAME | ORG_NAME |
|------------------|---------------|----------|
| cooking,painting | Award1,Award2 | Boyscout |
Here is SQLFiddle demo
and then in your client php code easily explode() column values while iterating over the resultset and build your presentation.
I think "Limit" can work:
SELECT h.hobby_name,r.recog_name,o.org_name
FROM hobbies as h,
nonacad_recog as r,
org_membership as o
WHERE h.employeeid='123'
AND r.employeeid=o.employeeid
AND h.employeeid=r.employeeid
LIMIT 1

Can't get my head around GROUP_CONCAT

I cannot seem to get an GROUP_CONCAT query to work.
I have this tables, which I joined:
stud
id | stud_name |
-----------------
1 | Class1 |
2 | Class2 |
note
id | stud_id | mat_id | Note |
------------------------------------------------
1 | 1 | 1 | 10 |
2 | 1 | 2 | 9 |
3 | 1 | 1 | 10 |
mat
id | mat_name |
----------------
1 | Porc |
2 | Vaca |
Here is what I did to join them.
SELECT
`stud`.`id`
, `mat`.`mat_name`
, `note`.`note`
FROM
`stud`
LEFT JOIN
`note`
ON
(`stud`.`id` = `note`.`id_stud`)
LEFT JOIN
`mat`
ON
(`note`.`id_mate` = `mat`.`id`)
Here is what I want them to look.
mat.id | mat_name | Note |
-----------------------------
1 | Porc | 10,10 |
2 | Vaca | 9 |
Here is how they look.
mat.id | mat_name | Note |
-----------------------------
1 | Porc | 10 |
2 | Vaca | 9 |
1 | Port | 10 |
I tried doing this.
SELECT
`mat`.`mat_name`,
GROUP_CONCAT(`note`.`note`) AS `note`.`note`,
FROM ( "Here is what I did to join them." )attr_groups
GROUP BY `mat`.`mat_name`;
ORDER BY `mat`.`mat_name`;
Any ideas?
EDIT: If I add group by or ORDER by, no results are found. If I don't add them, the query works but its not concatenating them.
SELECT mat.id,
mat.mat_name,
GROUP_CONCAT(note.note) as note
FROM mat
LEFT JOIN note ON mat.id = note.mat_id
LEFT JOIN stud ON note.stud_id = stud.id
GROUP BY mat.id, mat.mat_name
ORDER BY mat.mat_name
SQLFiddle demo
You have error in group by.
GROUP BY `mat`.`mat_name`;
------------------------^^^---
remove ; from query
SELECT
`stud`.`id`
, `mat`.`mat_name`
, GROUP_CONCAT(`note`.`note`) AS Note
FROM
`stud`
LEFT JOIN
`note`
ON
(`stud`.`id` = `note`.`id_stud`)
LEFT JOIN
`mat`
ON
(`note`.`id_mate` = `mat`.`id`)
GROUP BY
`stud`.mat_id
ORDER BY
`mat`.`mat_name`
Try this:
SELECT
m.id,
m.mat_name,
GROUP_CONCAT(n.Note) as grades
FROM
mat m
LEFT JOIN note n
ON n.mat_id = m.id
GROUP BY
m.id

MYSQL SELECT rank of user (more than x & less than y)

I'm a bit stuck with a php/Mysql Query. I got 2 tables :
table_users table_ranks
---------------- ------------------------
| id | points | | name | points_needed |
---------------- ------------------------
| 1 | 2 | | lvl0 | 0 |
| 2 | 10 | | lvl1 | 10 |
| 3 | 21 | | lvl2 | 20 |
| 4 | 29 | | lvl3 | 30 |
---------------- ------------------------
I need an ouput like this :
User_1 = lvl0 (because user has 2 points)
User_2 = lvl1 (because user has just reached 10 points)
...
User_4 = lvl2 (because user has not yet reached 30 points)
Think you :)
Regards.
You can do it like this
SELECT
tu.id,
tr.name,
tu.points
FROM table_ranks as tr
LEFT JOIN (SELECT * FROM table_ranks LIMIT 1,69596585953484) as l
ON l.points_needed = (SELECT MIN(points_needed) FROM table_ranks WHERE points_needed > tr.points_needed limit 1)
LEFT OUTER JOIN table_users AS tu ON tu.points >= tr.points_needed AND tu.points < l.points_needed
WHERE tu.id IS NOT NULL
group by tu.id
Fiddle
Output
-------------------------
| id | points | name |
-------------------------
| 1 | lvl0 | 2 |
| 2 | lvl1 | 10 |
| 3 | lvl2 | 21 |
| 4 | lvl2 | 29 |
-------------------------
give this a try, a little bit messy due to table design,
SELECT u.*, r.name
FROM table_users u
INNER JOIN
(
SELECT x.name,
x.points_needed start_point,
COALESCE(y.points_needed - 1, 2000000) end_point
FROM
(
SELECT name, points_needed, #rank:=#rank+1 ranks
FROM table_ranks a, (SELECT #rank:=0) b
ORDER BY points_needed
) x
LEFT JOIN
(
SELECT name, points_needed, #rank1:=#rank1+1 ranks
FROM table_ranks a, (SELECT #rank1:=0) b
ORDER BY points_needed
) y ON x.ranks+1 = y.ranks
) r ON u.points BETWEEN r.start_point AND r.end_point
SQLFiddle Demo

Find identical values from MySQL table from two columns

I need to filter only these table rows which have same values in x and y columns.
_______________________________________
|
| x | y | name |
________________________________________
|
| 1 | 2 | A |
|______________________________________
| 2 | 1 | B |
|______________________________________
| 1 | 2 | C |
|_______________________________________
The final result should be that I have A and C result. I need to filter these rows which has identical x and y values.
_______________________________________
|
| x | y | name |
________________________________________
|
| 1 | 2 | A |
|______________________________________
______________________________________
| 1 | 2 | C |
|_______________________________________
I' ve tried this code but I only managed to with one field.
select *
from auto
where x in (
select x
from auto
group by x
having count(*) > 1
);
SELECT t1.*
FROM tablename t1, tablename t2
WHERE t1.x = t2.x
AND t1.y = t2.y
AND t1.primary_key != t2.primary_key
select * from
auto a, ( SELECT x, y, COUNT(*) FROM auto GROUP BY x, y HAVING COUNT(*) > 1 ) b
where a.x = b.x
and a.y = b.y
will mark your other question as duplicate

Categories