MySQL query not giving results as expected - mysql

Below are two mysql tables. I want to check if the two people are in teams from Table: Teams and then getting their name and email from Table: Registration. I am having a hard time writing a mysql query for it.
Table: Registration
id: 1 name:jason email:jason#xyz.com
id: 2 name:kim email:kim#xyz.com
id: 3 name:tim email:tim#xyz.com
Table:Teams
team_id: 1 person1Id: 1 person2Id: 2
team_id: 2 person1Id: 1 person2Id: 3

You have to join the registration table twice and give them a unique alias
Schema (MySQL v8.0)
CREATE TABLE Teams (
`team_id` INTEGER,
`person1Id` VARCHAR(9),
`person2Id` INTEGER
);
INSERT INTO Teams
(`team_id`, `person1Id`, `person2Id`)
VALUES
('1', '1', '2'),
('1', '1', '3');
CREATE TABLE Registration (
`id` INTEGER,
`name` VARCHAR(5),
`email` VARCHAR(13)
);
INSERT INTO Registration
(`id`, `name`, `email`)
VALUES
('1', 'jason', 'jason#xyz.com'),
('2', 'kim', 'kim#xyz.com'),
('3','tim','tim#xyz.com');
Query #1
SELECT
t.team_id,r1.name,r1.email,r2.name,r2.email
FROM Teams t
INNER JOIN Registration r1 ON t.person1Id = r1.id
INNER JOIN Registration r2 ON t.person2Id = r2.id;
| team_id | name | email | name | email |
| ------- | ----- | ------------- | ---- | ----------- |
| 1 | jason | jason#xyz.com | kim | kim#xyz.com |
| 1 | jason | jason#xyz.com | tim | tim#xyz.com |
View on DB Fiddle

you can select both ids from Teams table and use in clause to get name and email from Registration table as
select name, email from Registration where id in(select person1Id, person2Id from Teams where team_id=1)

Related

How to show multiple results in single columns whith subquery

I have orders table where i show information about order number, products, and customer.
I need to show list of product names and their qty in column products separated or in new row like below in table:
Expected result
id | order_number | customer | address | total | products
------------------------------------------------------------------------------------
1 | OR00123 | Tom Helks | Test 221 | 1233,2 | 1x iphone
| 2x samsung
| 3x someproduct
Order table
id | order_number | customer_id | total | status_id
------------------------------------------------------------------------------------
1 | OR00123 | 1 | 1233,2 | 1
OrderProducts table
id | order_id | product_id | qty |
------------------------------------------------------
1 | 1 | 5 | 1 |
2 | 1 | 2 | 2 |
3 | 1 | 6 | 3 |
Product table
id | name | price
----------------------------------------
5 | iphone | 1231
2 | samsung | 2322
6 | someproduct | 432
What i try.
I get above expected result but only dont do subquery for listing products and qty for order.
SELECT
order.number,
customer.name,
customer.adress,
SUM(order_products.qty * product.price) as total,
# subquery here
(
SELECT p.name FROM products p WHERE order_products.product_id = p.id
) as products
FROM.orders as order
INNER JOIN customer on customer.customer_id= customer.id
INNER JOIN order_products on order.id = order_products.order_id
ORDER BY dok.created_at;
My imagination stopped and I believe that the problem is in the sub-query, but I can't see it at the moment.
Thanks
You need to join all tables and GROUP BY the unique values.
The GROUP_CONCAT has to be used with then CONCAT of the wanted values
CREATE TABLE orders
(`id` int, `order_number` varchar(7), `customer_id` int, `total` varchar(6), `status_id` int)
;
INSERT INTO orders
(`id`, `order_number`, `customer_id`, `total`, `status_id`)
VALUES
(1, 'OR00123', 1, '1233,2', 1)
;
CREATE TABLE orders_product
(`id` int, `order_id` int, `product_id` int, `qty` int)
;
INSERT INTO orders_product
(`id`, `order_id`, `product_id`, `qty`)
VALUES
(1, 1, 5, 1),
(2, 1, 2, 2),
(3, 1, 6, 3)
;)
Records: 3 Duplicates: 0 Warnings: 0
You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ')' at line 1
CREATE TABLE product
(`id` int, `name` varchar(11), `price` int)
;
INSERT INTO product
(`id`, `name`, `price`)
VALUES
(5, 'iphone', 1231),
(2, 'samsung', 2322),
(6, 'someproduct', 432)
;
Records: 3 Duplicates: 0 Warnings: 0
SELECT
order_number, `customer_id`, `total`,GROUP_CONCAT(CONCAT( op.`qty`,'x ',p.`name`) SEPARATOR ' ') products
FROM orders o
JOIN orders_product op ON o.`id` = op.`order_id`
JOIN product p ON op.`product_id` = p.`id`
GROUP BY order_number, `customer_id`, `total`
order_number
customer_id
total
products
OR00123
1
1233,2
1x iphone 2x samsung 3x someproduct
fiddle

GROUP BY + HAVING ignore row

Basically what I wanted is that I can select all the race records with record holder and best time. I looked up about similar queries and managed to find 3 queries that were faster than the rest.
The problem is it completely ignores the race the userid 2 owns the record of.
These are my tables, indexes, and some sample data:
CREATE TABLE `races` (
`raceid` smallint(5) unsigned NOT NULL AUTO_INCREMENT,
`name` varchar(20) NOT NULL,
PRIMARY KEY (`raceid`),
UNIQUE KEY `name` (`name`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
CREATE TABLE `users` (
`userid` mediumint(8) unsigned NOT NULL AUTO_INCREMENT,
`name` varchar(20) NOT NULL,
PRIMARY KEY (`userid`),
UNIQUE KEY `name` (`name`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
CREATE TABLE `race_times` (
`raceid` smallint(5) unsigned NOT NULL,
`userid` mediumint(8) unsigned NOT NULL,
`time` mediumint(8) unsigned NOT NULL,
PRIMARY KEY (`raceid`,`userid`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
INSERT INTO `races` (`raceid`, `name`) VALUES
(1, 'Doherty'),
(3, 'Easter Basin Naval S'),
(5, 'Flint County'),
(6, 'Fort Carson'),
(4, 'Glen Park'),
(2, 'Palomino Creek'),
(7, 'Tierra Robada');
INSERT INTO `users` (`userid`, `name`) VALUES
(1, 'Player 1'),
(2, 'Player 2');
INSERT INTO `race_times` (`raceid`, `userid`, `time`) VALUES
(1, 1, 51637),
(1, 2, 50000),
(2, 1, 148039),
(3, 1, 120516),
(3, 2, 124773),
(4, 1, 101109),
(6, 1, 89092),
(6, 2, 89557),
(7, 1, 77933),
(7, 2, 78038);
So if I run these 2 queries:
SELECT rt1.raceid, r.name, rt1.userid, p.name, rt1.time
FROM race_times rt1
LEFT JOIN users p ON (rt1.userid = p.userid)
JOIN races r ON (r.raceid = rt1.raceid)
WHERE rt1.time = (SELECT MIN(rt2.time) FROM race_times rt2 WHERE rt1.raceid = rt2.raceid)
GROUP BY r.name;
or..
SELECT rt1.*, r.name, p.name
FROM race_times rt1
LEFT JOIN users p ON p.userid = rt1.userid
JOIN races r ON r.raceid = rt1.raceid
WHERE EXISTS (SELECT NULL FROM race_times rt2 WHERE rt2.raceid = rt1.raceid
GROUP BY rt2.raceid HAVING MIN(rt2.time) >= rt1.time);
I receive correct results as shown below:
raceid | name | userid | name | time |
-------+----------------------+--------+----------+--------|
1 | Doherty | 2 | Player 2 | 50000 |
3 | Easter Basin Naval S | 1 | Player 1 | 120516 |
6 | Fort Carson | 1 | Player 1 | 89092 |
4 | Glen Park | 1 | Player 1 | 101109 |
2 | Palomino Creek | 1 | Player 1 | 148039 |
7 | Tierra Robada | 1 | Player 1 | 77933 |
and here is the faulty query:
SELECT rt.raceid, r.name, rt.userid, p.name, rt.time
FROM race_times rt
LEFT JOIN users p ON p.userid = rt.userid
JOIN races r ON r.raceid = rt.raceid
GROUP BY r.name
HAVING rt.time = MIN(rt.time);
and the result is this:
raceid | name | userid | name | time |
-------+----------------------+--------+----------+--------|
3 | Easter Basin Naval S | 1 | Player 1 | 120516 |
6 | Fort Carson | 1 | Player 1 | 89092 |
4 | Glen Park | 1 | Player 1 | 101109 |
2 | Palomino Creek | 1 | Player 1 | 148039 |
7 | Tierra Robada | 1 | Player 1 | 77933 |
As you can see, race "Doherty" (raceid: 1) is owned by "Player 2" (userid: 2) and it is not shown along with the rest of race records (which are all owned by userid 1). What is the problem?
Regards,
Having is a post filter. The query gets all the results, and then further filters them based on having. The GROUP BY compacting the rows based on the group, which gives you the first entry in each set. Since player 1 is the first entry for race 1, that's the result that is being processed by the HAVING. It is then filtered out because its time does not equal the MIN(time) for the group result.
This is why the other ones you posted are using a sub-query. My personal preference is for the first example, as to me it's slightly easier to read. Performance wise they should be the same.
While it's not a bad idea to try and avoid sub queries in the where clause, this is mostly valid when you can accomplish the same result with a JOIN. Other times it's not possible to get the result with a JOIN and a sub query is required.

From SELECT to UPDATE in MySQL

I would like you to help me with this, I have a little problem with this, but I don't know how I can fix it, basically I want to update the so called duplicatedusernameid, and update it into the users database. Here is my code:
UPDATE users SET duplicatedusernameid = (SELECT CONCAT(first_name,middle_name,last_name)
,COUNT(*)-1 AS duplicatedusernameid HAVING COUNT(*) > 1) WHERE id = 1
And here is the working SELECT function, but instead of select I want UPDATE, like the one above, but that one doesn't work. Here is the SELECT code:
SELECT CONCAT(first_name,middle_name,last_name),COUNT(*)-1 AS duplicatedusernameid
FROM users HAVING COUNT(*) > 1
So basically I want to get the value of the duplicatedusernameid and update it.
You can use a SQL statement like this:
update users a
inner join (
-- get the count for a user
SELECT first_name, middle_name, last_name, COUNT(*)-1 AS duplicatedusernameid
from users
group by first_name, middle_name, last_name
) b
on a.first_name = b.first_name
and a.middle_name = b.middle_name
and a.last_name = b.last_name
set a.duplicatedusernameid = b.duplicatedusernameid
where a.id = 1;
Table
create table users (
id int,
first_name varchar(100),
middle_name varchar(100),
last_name varchar(100),
duplicatedusernameid varchar(100)
);
insert into users (id, first_name, middle_name, last_name) values
(1, 'John', '', 'Smith'),
(2, 'John', '', 'Smith'),
(3, 'Jessie', '', 'Marcus'),
(4, 'Jessie', '', 'Marcus'),
(5, 'Jessie', '', 'Marcus'),
(6, 'Don', '', 'Kassieth');
Results (if you remove the where clause)
| id | first_name | middle_name | last_name | duplicatedusernameid |
|----|------------|-------------|-----------|----------------------|
| 1 | John | | Smith | 1 |
| 2 | John | | Smith | 1 |
| 3 | Jessie | | Marcus | 2 |
| 4 | Jessie | | Marcus | 2 |
| 5 | Jessie | | Marcus | 2 |
| 6 | Don | | Kassieth | 0 |
Explanation
SELECT first_name, middle_name, last_name, COUNT(*)-1 AS duplicatedusernameid
from users
group by first_name, middle_name, last_name
The above SQL statement will get the count for each unique first, middle and last name combination. You can shortlist this by adding having count(*) > 1 below the group by clause.
We then join users table with this count-related table based on first, middle and last name combination. Wherever there is a match, update the retrieved count in the users table.
SQLFiddle
http://sqlfiddle.com/#!9/c43ea/1

MySQL query eleminating duplicates from second table

I have two mysql tables: table_1 and table_2.
table_1:
| c_id | name | email |
| 1 | tom | t#t.com |
table_2:
| a_id | c_id | address | street |
| 1 | 1 | 67 | home |
| 2 | 1 | 68 | main |
How to create mysql query that will select table_1.name, table_1.email, table_2.address and table_2.street returning only one record like:
| name | email | address | street |
| tom | t#t.com | 67 | home |
Thanks for any suggestion.
Regards, T
Try this:
SELECT table_1.name, table_1.email, table_2.address, table_2.street
FROM table_1
JOIN table_2
ON table_1.c_id = table_2.c_id
GROUP BY table_1.c_id
SQLfiddle demo
The GROUP BY will determine which column you want to use to group the results by. B.T.W. if you like the change the column head you can add AS followed by the column head name (table_1.name AS "First name").
Table structure and sample data:
CREATE TABLE table_1
(`c_id` int, `name` varchar(3), `email` varchar(7))
;
INSERT INTO table_1
(`c_id`, `name`, `email`)
VALUES
(1, 'tom', 't#t.com')
;
CREATE TABLE table_2
(`a_id` int, `c_id` int, `address` int, `street` varchar(4))
;
INSERT INTO table_2
(`a_id`, `c_id`, `address`, `street`)
VALUES
(1, 1, 67, 'home'),
(2, 1, 68, 'main')
;
If you like to limit the sql query to a certain person say tom WHERE table_1.name LIKE 'Tom'. Like so:
SELECT table_1.name, table_1.email, table_2.address, table_2.street
FROM table_1
JOIN table_2
ON table_1.c_id = table_2.c_id
WHERE table_1.name LIKE 'Tom'
GROUP BY table_1.c_id;
You can also use = but with LIKE you can use wildcards like T%
you should use the SQL statement LEFT JOIN, for example
SELECT name, email, address, street
FROM table1
LEFT JOIN table2
ON table1.c_id=table2.c_id;
with the possible option WHERE name = 'tom'
select table_1.name as name, table_1.email as email, table_2.address as address, table_2.street as street
from table_1
left join table_2 on table_1.c_id = table_2.c_id

How to select from separate subclasses' tables?

I have a pretty simple database. The idea is that Student and Teacher both inherit from "Person" which is made of id and name.
create table Student (
id int,
name text,
year int
);
create table Teacher (
id int,
name text,
department varchar(15)
);
insert into Student (id, name, year) values
(1, 'herper', 2007),
(2, 'derpins', 2010);
insert into Teacher (id, name, department) values
(3, 'skerp', 'csc');
I'm trying to make a select statement that will return this:
id name year department
1 'herper' 2007 NULL
2 'derpins' 2010 NULL
3 'skerp' NULL 'csc'
This is the closest I've gotten:
select *
from Student
union
select * from Teacher;
Any ideas? Thanks!
SELECT id, name, year, NULL department
FROM Student
UNION
SELECT id, name, NULL, department
FROM Teacher;
Output:
| ID | NAME | YEAR | DEPARTMENT |
--------------------------------------
| 1 | herper | 2007 | (null) |
| 2 | derpins | 2010 | (null) |
| 3 | skerp | (null) | csc |
SQLFiddle