I've currently got 3 different queries to check for multiple users in database, I was wondering if there is a way to combine then all in a single query.
Based on email:
SELECT
user_email,
COUNT(user_email)
FROM
users
GROUP BY user_email
HAVING COUNT(user_email) > 1;
Based on last name:
SELECT
user_lastname,
COUNT(user_lastname)
FROM
users
GROUP BY user_lastname
HAVING COUNT(user_lastname) > 1;
Based on phone:
SELECT
user_phone,
COUNT(user_phone)
FROM
users
GROUP BY user_phone
HAVING COUNT(user_phone) > 1;
For each query I am showing a list of email|last name|phone number and the number of multiple users there are.
My final plan is to make a list with just the duplicate users containing just the information they got caught on (for example user X / Y duplicate based on U email etc).
User_ID | user_email | user_firstname | user_lastname | user_phone
1 | snow#asd.com | John | Snow | 123456
2 | user#asd.com | George | Smith | 546632
3 | usr#asd.com | Maria | Coal | 553211
4 | snow#asd.com | Jack | Black | 752210
5 | bin#asd.com | Tom | Bing | 856332
6 | col#asd.com | Storm | Snow | 325412
7 | ding#asd.com | Mairy | Call | 123456
8 | user23#asd.com | Kim | Loren | 351200
9 | user44#asd.com | Dot | Honey | 546632
10 | user11#asd.com | Jack | Smithson | 455871
The end result must show users 1+4 (same email) +7 (same phone number with 1) +6 (same last name with 1) + 2+9 (same phone number)
User_ID | user_email | user_firstname | user_lastname | user_phone
1 | snow#asd.com | John | Snow | 123456
4 | snow#asd.com | Jack | Black | 752210
6 | col#asd.com | Storm | Snow | 325412
7 | ding#asd.com | Mairy | Call | 123456
2 | user#asd.com | George | Smith | 546632
9 | user44#asd.com | Dot | Honey | 546632
For this case I think that EXISTS is the best solution:
select u.* from users u
where exists (
select 1 from users
where user_id <> u.user_id
and (user_lastname = u.user_lastname or user_email = u.user_email or user_phone = u.user_phone)
)
See the demo.
Results:
| User_ID | user_email | user_firstname | user_lastname | user_phone |
| ------- | -------------- | -------------- | ------------- | ---------- |
| 1 | snow#asd.com | John | Snow | 123456 |
| 2 | user#asd.com | George | Smith | 546632 |
| 4 | snow#asd.com | Jack | Black | 752210 |
| 6 | col#asd.com | Storm | Snow | 325412 |
| 7 | ding#asd.com | Mairy | Call | 123456 |
| 9 | user44#asd.com | Dot | Honey | 546632 |
Related
this is my first time posting here. I don't seem to find the answer to my problem.
So... I'm arranging a DB for a school project, a cookbook that only shows recipes that can be made with existing elements from the "shelf".
These ingredients have to have an exact ingredients match.
user:
+---------------+------+----------+----------+
| email | name | lastname | password |
+---------------+------+----------+----------+
| pal#mail.com | John | Potato | password |
| they#mail.com | Mary | Carrot | password |
+---------------+------+----------+----------+
shelf:
+---------+------------+---------------+
| shelfID | ingredient | user |
+---------+------------+---------------+
| 1 | 1 | pal#mail.com |
| 2 | 2 | pal#mail.com |
| 3 | 3 | pal#mail.com |
| 4 | 4 | pal#mail.com |
| 5 | 10 | they#mail.com |
| 6 | 12 | they#mail.com |
+---------+------------+---------------+
This is my recipe_ingredient relationship table
recipe_ingredient:
+--------+------------+
| recipe | ingredient |
+--------+------------+
| 1 | 1 |
| 1 | 2 |
| 1 | 4 |
| 1 | 10 |
| 2 | 1 |
| 2 | 2 |
| 2 | 3 |
| 2 | 4 |
| 3 | 2 |
| 3 | 3 |
| 3 | 15 |
+--------+------------+
I've tried this query:
SELECT
rec_ing.recipe, shf.ingredient, shf.user
FROM
recipes_ingredients AS rec_ing
INNER JOIN
shelf AS shf ON rec_ing.ingredient = shf.ingredient
INNER JOIN
users AS usr ON shf.user = usr.email
WHERE
usr.email = 'pal#mail.com'
that returns this table:
+--------+------------+--------------+
| recipe | ingredient | user |
+--------+------------+--------------+
| 1 | 1 | pal#mail.com |
| 1 | 2 | pal#mail.com |
| 1 | 4 | pal#mail.com |
| 2 | 1 | pal#mail.com |
| 2 | 2 | pal#mail.com |
| 2 | 3 | pal#mail.com |
| 2 | 4 | pal#mail.com |
| 3 | 2 | pal#mail.com |
| 3 | 3 | pal#mail.com |
+--------+------------+--------------+
Although it's true that the Recipe 1 contains ingredients from my shelf, it's also missing Ingredient 10
+--------+------------+
| recipe | ingredient |
+--------+------------+
| 1 | 1 |
| 1 | 2 |
| 1 | 4 |
| 1 | 10 |
| ... | ... |
+--------+------------+
I'm trying to only get this kind of result set.
+--------+------------+
| recipe | ingredient |
+--------+------------+
| 2 | 1 |
| 2 | 2 |
| 2 | 3 |
| 2 | 4 |
+--------+------------+
Because Recipe 2 contains all elements from my shelf
I have been going around all day with this problem ... What could be missing?
This is a bit tricky, because you need to aggregate your current query by recipe, but you also need the original query to get back the full records. Sadly, MySQL does not support common table exprrssions or other features which could give us a less verbose query.
SELECT
rec_ing.recipe,
shf.ingredient,
shf.user
FROM recipes_ingredients AS rec_ing
INNER JOIN shelf AS shf
ON rec_ing.ingredient = shf.ingredient
INNER JOIN users AS usr
ON shf.user = usr.email
INNER JOIN
(
SELECT rec_ing.recipe
FROM recipes_ingredients AS rec_ing
INNER JOIN shelf AS shf
ON rec_ing.ingredient = shf.ingredient
LEFT JOIN users AS usr
ON shf.user = usr.email
WHERE
usr.email = 'pal#mail.com'
GROUP BY rec_ing.recipe
HAVING COUNT(usr.email) = COUNT(*)
) t
ON rec_ing.recipe = t.recipe
WHERE
usr.email = 'pal#mail.com'
The basic strategy here is to just do one additional join to a subquery which identifies all recipes where every ingredient belongs to a given user. The critical part is the following:
HAVING COUNT(usr.email) = COUNT(*)
This checks that the total number of rows for a given recipe matches the number of rows which have been assigned to a given user.
[Ask] Please help, for example, there is a data
tbl_user
| Id | name |
| 1 | Bayu |
| 2 | Indra |
| 3 | Rangga |
tbl_data
| Id | userId | items |
| 1 | 1 | Knife |
| 2 | 3 | CD |
| 3 | 1 | Rose |
| 4 | 3 | HP |
| 5 | 2 | Honey |
| 6 | 1 | cups |
| 7 | 1 | Yarn |
| 8 | 2 | Shoes |
I want to sort by items table data is only logged user access
so for example when user Bayu logged in sorting results of the data is the top itself and of the data persists
userId | items |
1 | Yarn |
1 | cups |
1 | Knife |
1 | Rose |
2 | Honey |
2 | Shoes |
3 | CD |
3 | HP |
when Indra login the results of the sort:
userId | items |
2 | Honey |
2 | Shoes |
1 | Yarn |
1 | cups |
1 | Knife |
1 | Rose |
3 | CD |
3 | HP |
or when Rangga login
userId | items |
3 | CD |
3 | HP |
1 | Yarn |
1 | cups |
1 | Knife |
1 | Rose |
2 | Honey |
2 | Shoes |
How to query (MySQL) select it?
Try this:
select userId, items
from tbl_data
order by userId=:userId desc, userId asc;
For example if Indra logged in:
select userId, items
from tbl_data
order by userId=2 desc, userId asc;
imaging when a user login, there will be a $userID pass in on the page:
$sql = "
SELECT userId,items
FROM tbl_data
ORDER BY if (userID = $userId, 0, userId)";
Not the most elegant, but this should do trick:
SELECT userID, items FROM tbl_data, tbl_user where userId=tbl_user.id AND tbl_user.name=CURRENT_USER()
UNION
SELECT userID, items FROM tbl_data, tbl_user WHERE userId<>tbl_user.id AND tbl_user.name=CURRENT_USER();
First you have to userID order by with logged in user and then order by other userId in ascending and descending order.
select userId, items
from tbl_data
order by FIELD(userId , $userId) desc, userId asc;
I am trying to write a query to bring together data from three tables:
---------------------------------
| destinations |
---------------------------------
| id | city | status |
---------------------------------
| 1 | Milan | Open |
| 2 | Florence | Open |
| 3 | Venice | Open |
---------------------------------
---------------------------------
| trips |
---------------------------------
| id | from | to | train |
---------------------------------
| 1 | 1 | 2 | 2 |
| 2 | 1 | 2 | 3 |
| 3 | 2 | 1 | 2 |
| 4 | 2 | 3 | 2 |
| 5 | 1 | 3 | 1 |
| 6 | 3 | 1 | 1 |
---------------------------------
---------------------------------
| trains |
---------------------------------
| id | train |
---------------------------------
| 1 | T1 |
| 2 | ChooChoo |
| 3 | IC123 |
---------------------------------
The idea is that I would like to be able to show my user all the trips starting or ending in - say - Florence.
Something along these lines:
-----------------------------------------------------------------
| Query: all trains going to/from Florence |
-----------------------------------------------------------------
| trips.id | from.id | from (city) | to.id | to. city | train |
-----------------------------------------------------------------
| 1 | 1 | Milan | 2 | Florence | 2 |
| 2 | 1 | Milan | 2 | Florence | 3 |
| 3 | 2 | Florence | 1 | Milan | 2 |
| 4 | 2 | Florence | 3 | Venice | 2 |
-----------------------------------------------------------------
The problems that I'm facing are essentially two: the auto-referencing table of destinations (which I can easily solve with aliases) and the fact that I am trying to combine two sets of data from two different selects (which I thought of solving with temporary tables).
Now, it's all good if it wasn't that some columns have the same names. Because I want to preserve the "ids" in my temporary table (to be used with links) I can't create a temporary table with a wildcard (eg. SELECT * FROM), but I would have to spell out all the columns and write a monstrous query. It will work, but it won't be flexible, and if I'll add other columns in the future, it will be hell updating it!
Can any MySQL guru maybe suggest a better approach please?
Thanks and cheers from Australia.
G'day...
DROP TABLE IF EXISTS destinations;
CREATE TABLE destinations
(city_id INT NOT NULL AUTO_INCREMENT PRIMARY KEY
,city VARCHAR(12) NOT NULL UNIQUE
,status VARCHAR(12) NOT NULL
);
INSERT INTO destinations VALUES
(1,'Milan','Open'),
(2,'Florence','Open'),
(3,'Venice','Open');
DROP TABLE IF EXISTS trips;
CREATE TABLE trips
(trip_id INT NOT NULL AUTO_INCREMENT PRIMARY KEY
,from_city_id INT NOT NULL
,to_city_id INT NOT NULL
,train INT NOT NULL
,UNIQUE(from_city_id,to_city_id,train)
);
INSERT INTO trips VALUES
(1,1,2,2),
(2,1,2,3),
(3,2,1,2),
(4,2,3,2),
(5,1,3,1),
(6,3,1,1);
DROP TABLE IF EXISTS trains;
CREATE TABLE trains
(train_id INT NOT NULL AUTO_INCREMENT PRIMARY KEY
,train VARCHAR(12) NOT NULL UNIQUE
);
INSERT INTO trains VALUES
(1,'T1'),
(2,'ChooChoo'),
(3,'IC123');
SELECT * FROM destinations;
+---------+----------+--------+
| city_id | city | status |
+---------+----------+--------+
| 1 | Milan | Open |
| 2 | Florence | Open |
| 3 | Venice | Open |
+---------+----------+--------+
SELECT * FROM trips;
+---------+--------------+------------+-------+
| trip_id | from_city_id | to_city_id | train |
+---------+--------------+------------+-------+
| 1 | 1 | 2 | 2 |
| 2 | 1 | 2 | 3 |
| 5 | 1 | 3 | 1 |
| 3 | 2 | 1 | 2 |
| 4 | 2 | 3 | 2 |
| 6 | 3 | 1 | 1 |
+---------+--------------+------------+-------+
SELECT * FROM trains;
+----------+----------+
| train_id | train |
+----------+----------+
| 2 | ChooChoo |
| 3 | IC123 |
| 1 | T1 |
+----------+----------+
SELECT t.trip_id
, t.from_city_id
, from_city.city
, t.to_city_id
, to_city.city
, t.train
FROM trips t
JOIN destinations from_city
ON from_city.city_id = t.from_city_id
JOIN destinations to_city
ON to_city.city_id = t.to_city_id
WHERE 'Florence' IN(from_city.city,to_city.city);
+---------+--------------+----------+------------+----------+-------+
| trip_id | from_city_id | city | to_city_id | city | train |
+---------+--------------+----------+------------+----------+-------+
| 3 | 2 | Florence | 1 | Milan | 2 |
| 4 | 2 | Florence | 3 | Venice | 2 |
| 1 | 1 | Milan | 2 | Florence | 2 |
| 2 | 1 | Milan | 2 | Florence | 3 |
+---------+--------------+----------+------------+----------+-------+
when you build a report, usually isn't a good idea to use SELECT *,
because when i modify a table, the report can shows wrong result.
usually i prefere to write the id field with id_content, ex. id_destination, id_to, id_train, ecc...
SELECT trips.id, f.id, f.city, t.id, t. city, trains.train
FROM trips trips
INNER JOIN destinations f
ON trips.from = f.id
INNER JOIN destinations t
ON trips.from = t.id
INNER JOIN trains trains
ON trips.train = trains.id
ORDER BY 1 ASC
I am looking to overwrite a column name in a table with an existing column name.
I am Looking for a way to get the remaining unspecified columns in the tables.
Note:
The query could have more joins in the future.
eg
Person
+-----------+----------+---------+
| firstname | lastname | pers_id |
+-----------+----------+---------+
| Joe | Soap | 1 |
| Bobby | Pin | 2 |
| Janet | Jackson | 3 |
+-----------+----------+---------+
Category
+----------+-------------------+--------+
| type | description | cat_id |
+----------+-------------------+--------+
| customer | people who pay us | 1 |
| employee | people we pay | 2 |
| director | people who direct | 3 |
+----------+-------------------+--------+
Person_Cat
(=^ェ^=)
+---------+--------+
| pers_id | cat_id |
+---------+--------+
| 3 | 1 |
| 2 | 2 |
| 1 | 3 |
+---------+--------+
Query
SELECT *, CONCAT(p.firstname, ' '
, p.lastname) as full_name
, c.cat_id AS category_id
, p.pers_id AS cat_id
FROM Person AS p
JOIN Person_Cat AS pc ON(p.pers_id = pc.pers_id)
JOIN Category AS c ON (pc.cat_id = c.cat_id)
OUTPUT
(Apologies for the length but the table after is more important)
+-----------+----------+---------+---------+--------+----------+-------------------+--------+---------------+-------------+--------+
| p | p | p | pc | pc | c | c | c | Select | Select | Select |
+-----------+----------+---------+---------+--------+----------+-------------------+--------+---------------+-------------+--------+
| firstname | lastname | pers_id | pers_id | cat_id | type | description | cat_id | full_name | category_id | cat_id |
+-----------+----------+---------+---------+--------+----------+-------------------+--------+---------------+-------------+--------+
| Janet | Jackson | 3 | 3 | 1 | customer | people who pay us | 1 | Janet jackson | 1 | 3 |
| Bobby | Pin | 2 | 2 | 2 | employee | people who we pay | 2 | Bobby Pin | 2 | 2 |
| Joe | Soap | 1 | 1 | 3 | director | people who direct | 3 | Joe Soap | 3 | 1 |
+-----------+----------+---------+---------+--------+----------+-------------------+--------+---------------+-------------+--------+
The headers above column names are there for reference
to where they comes from.
Column summary -
firstname, lastname, pers_id, pers_id, cat_id, type,
description, cat_id, full_name ,category_id, cat_id
Wanted output
+-----------+----------+---------+--------+----------+-------------------+---------------+-------------+--------+
| p | p | pc | pc | c | c | Select | Select | Select |
+-----------+----------+---------+--------+----------+-------------------+---------------+-------------+--------+
| firstname | lastname | pers_id | cat_id | type | description | full_name | category_id | cat_id |
+-----------+----------+---------+--------+----------+-------------------+---------------+-------------+--------+
| Janet | Jackson | 3 | 1 | customer | people who pay us | Janet jackson | 1 | 3 |
| Bobby | Pin | 2 | 2 | employee | people who we pay | Bobby Pin | 2 | 2 |
| Joe | Soap | 1 | 3 | director | people who direct | Joe Soap | 3 | 1 |
+-----------+----------+---------+--------+----------+-------------------+---------------+-------------+--------+
Column summary -
firstname, lastname, pers_id, cat_id, type,
description, full_name ,category_id, cat_id
Notice:
The p.pers_id and the c.cat_id are not present. I would like to think this would be because the were called directly and unmodified unlike the first and lastname used in ConCat
When the short answer is that there is no such concept as Select [remaining columns]at this time (2015-06-17), if you want to use SELECT * but only remove redundant columns,
then you will need to explicitly remove (ignore) those redundant columns when rendering your view.
You will have to explicitly configure logic of which columns to ignore, which is pretty much the same thing as explicitly listing the columns that you are interested in, so you get back to the argument against selecting all columns that I made in the comments above.
Unless your table schema is changing all the time, there really isn't reason for this.
I have two tables that look like this:
Table A:
+-----+-----+------+-------+
| aID | uID | attr | value |
+-----+-----+------+-------+
| 1 | 1 | fn | john |
+-----+-----+------+-------+
| 2 | 1 | ln | smith |
+-----+-----+------+-------+
| 3 | 2 | fn | jim |
+-----+-----+------+-------+
| 4 | 2 | ln | bean |
+-----+-----+------+-------+
Table B:
+-----+-----+-------+-------+
| bID | uID | perm | value |
+-----+-----+-------+-------+
| 1 | 1 | admin | 1 |
+-----+-----+-------+-------+
| 2 | 2 | news | 1 |
+-----+-----+-------+-------+
| 3 | 2 | cms | 1 |
+-----+-----+-------+-------+
As it shows, Table A holds attribute data for a user uID, and Table B holds permission data for a user uID.
At the moment, I am using,:
SELECT GROUP_CONCAT(`a`.`attr`) AS `attrs`
, GROUP_CONCAT(`a`.`value`) AS `values`
, GROUP_CONCAT(`b`.`perm`) AS `perms`
FROM `a`
JOIN `b`
ON `a`.`uID` = `b`.`uID`
GROUP BY `a`.`uID`, `b`.`uID`
But it is giving me a result:
+-------------+-------------------+-------------------+
| attrs | values | perms |
+-------------+-------------------+-------------------+
| fn,ln | John,Smith | admin,admin |
+-------------+-------------------+-------------------+
| fn,fn,ln,ln | Jim,Jim,Bean,Bean | news,cms,news,cms |
+-------------+-------------------+-------------------+
What do I need to change in my query to get:
+-------+------------+----------+
| attrs | values | perms |
+-------+------------+----------+
| fn,ln | John,Smith | admin |
+-------+------------+----------+
| fn,fn | Jim,Bean | news,cms |
+-------+------------+----------+
GROUP_CONCAT takes additional arguments, as explained on its documentation page here.
The one you want is distinct:
SELECT GROUP_CONCAT(distinct `a`.`attr`) AS `attrs` . . .