How to select from separate subclasses' tables? - mysql

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

Related

How to join tables based on ids and names with multiple values

I have 3 mysql tables:
Users:
id | name | interest | user_id
1 | user1 | 1,2 | 1
2 | user2 | 1,2,3 | 2
Interests:
id | name
1 | interest1
2 | interest2
User_posts:
id | user_id | desc
1 | 23 | something..
2 | 31 | something..
What i want to achieve is i want join interest column from users table into user_posts table based on user_id with user_name from interests table which i have already done using this query:
select user_posts.*, users.interest as interest_ids, zaya.interests.name as interest_name
from user_posts
left join users ON user_posts.id = users.interest
left join interests ON user_posts.id = users.interest;
i get the following output with this query:
User_posts:
id | user_id | desc | interest_ids | interest_name
1 | 23 | something.. | 1,2 | interest1
2 | 31 | something.. | 1,2,3 | interest1
Output i want to achieve:
User_posts:
id | user_id | desc | interest_ids | interest_name
1 | 23 | something.. | 1,2 | interest1, interest2
2 | 31 | something.. | 1,2,3 | interest1, interest2, interest3
I believe this can be solved using the temporary table creation method and have tried solving this but i'm newbie in mysql queries and getting errors please help me with the correct query.
Thank you in advance.
I would use a sub query rather than a join if you're looking to just get back one col form the [interests] table.
Here is an example using STRING_SPLIT function to get the names :
DECLARE #users TABLE(
[ID] int IDENTITY(1,1)
,[NAME] varchar(32)
,[INTERESTS] varchar(32)
)
INSERT INTO #users
VALUES ('user1', '1,2'), ('user2', '1,2,3')
DECLARE #interests TABLE(
[ID] int IDENTITY(1,1)
,[NAME] varchar(32)
)
INSERT INTO #interests
VALUES ('interests1'), ('interests2'), ('interests3')
DECLARE #user_posts TABLE(
[ID] int IDENTITY(1,1)
,[USERID] int
,[DESC] varchar(32)
)
INSERT INTO #user_posts
VALUES (1, 'post1'), (2, 'post2')
SELECT
U.[ID]
,UP.[USERID]
,UP.[DESC]
,U.[INTERESTS]
,SUBSTRING((SELECT ',' + I2.[NAME]
FROM #interests I2
WHERE I2.[ID] IN (SELECT [name] FROM STRING_SPLIT(U.[INTERESTS], ','))
FOR XML PATH('')), 2, 1000) AS 'INTEREST_NAME'
FROM #user_posts UP
LEFT JOIN #users U
ON U.[ID] = UP.[USERID]
This should return :
ID
USERID
DESC
INTERESTS
INTEREST_NAME
1
1
post1
1,2
interests1,interests2
2
2
post2
1,2,3
interests1,interests2,interests3

SQL - Manually obtain the next available ID for the given format

I'm trying to construct a single, simple SQL SELECT statement that manually provides the next unique ID available for the given format.
For an example, please see the table below.
-- Students (Table)
-- ID - Not a primary key
-- Type - Numbering format
+----------+------+
| ID | Type |
+----------+------+
| 1 | M |
| 2 | M |
| 5 | M |
| 7056 | F |
| 7057 | F |
| 7058 | F |
| 7090 | F |
| 7091 | N |
| 10910 | N |
| 10911 | N |
| 99000000 | O |
| 99000001 | O |
+----------+------+
-- Some of the available values:
+---+------+-------+----------+
| M | F | N | O |
+---+------+-------+----------+
| 6 | 7092 | 10912 | 99000002 |
| 7 | 7093 | 10913 | 99000003 |
| 8 | 7094 | 10914 | 99000004 |
+---+------+-------+----------+
Here, say I want to get '7092' for the type 'F' as the next value. But if I use the MAX function, it will return '99000002'.
SELECT MAX(id)+1 FROM students;
If I use the type column, I could get '7091' for the type 'F', but that's not available since it is used by another type.
SELECT MAX(id)+1 FROM students WHERE type = 'F';
This also does not work.
SELECT MAX(id)+1
FROM students
WHERE type = 'F'
AND id NOT IN ( SELECT DISTINCT id FROM students)
I am not able to change the database structure. If so, for the given scenario, is there a way (single SELECT statement) to get the next available ID for the selected type (e.g.: type F)?
I use Oracle 10g, but MySQL and SQL Server are okay as well.
CREATE TABLE students (
id NUMBER,
type CHAR(1)
);
INSERT INTO students VALUES (1, 'M');
INSERT INTO students VALUES (2, 'M');
INSERT INTO students VALUES (5, 'M');
INSERT INTO students VALUES (7056, 'F');
INSERT INTO students VALUES (7057, 'F');
INSERT INTO students VALUES (7058, 'F');
INSERT INTO students VALUES (7090, 'F');
INSERT INTO students VALUES (7091, 'N');
INSERT INTO students VALUES (10910, 'N');
INSERT INTO students VALUES (10911, 'N');
INSERT INTO students VALUES (99000000, 'O');
INSERT INTO students VALUES (99000001, 'O');
I would be grateful for any assistance. In any case, thank you for your time.
You're looking for the gaps, in consequence you're looking for the values NOT IN the id list.
The following query will give you a list of all the id's NOT IN the table.
SELECT sub_id FROM (
SELECT id+1 as sub_id FROM students
)sub_table WHERE sub_id NOT IN (
SELECT id FROM students
);
Then you can select the MIN() of that list:
SELECT MIN(sub_id) FROM (
SELECT id+1 as sub_id FROM students
)sub_table WHERE sub_id NOT IN (
SELECT id FROM students
);
Bear in mind that this will work only if you already have at least one id and it won't start from 1 unless you already have the id 1.
Notice: that the first query only gives you the list of all the gaps plus the next available id.
You can use:
SELECT COALESCE(MAX(id) + 1,1) AS next_id
FROM (
SELECT id,
ROW_NUMBER() OVER (ORDER BY id) AS rn
FROM students
)
WHERE id = rn;
or:
SELECT COALESCE(MAX(id + 1), 1) AS next_id
FROM students
WHERE CONNECT_BY_ISLEAF = 1
START WITH id = 1
CONNECT BY PRIOR id + 1 = id;
Which, for your sample data, both output:
NEXT_ID
3
Note: These queries will both return 1 if the first id value is deleted.
However, a better solution would be to use a sequence and let that handle generating the keys and not to worry about gaps between values.
db<>fiddle here

MySQL query not giving results as expected

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)

Join two tables matching multiple ID's to names

Fiddle here: http://sqlfiddle.com/#!9/53d3c/2/0
I have two tables, one containing Member Names and their ID Number. Let's call that table Names:
CREATE TABLE Names (
ID int,
Title text
);
INSERT INTO Names
VALUES (11,'Chad'),
(10,'Deb'),
(34,'Steph'),
(13,'Chris'),
(98,'Peter'),
(33,'Daniel'),
(78,'Christine'),
(53,'Yolanda')
;
My second table contains meeting information, where someone is a Coach and someone is a Player. Each entry is a separate line (i.e. Meeting_ID 1 has two entries, one for the coach, one for the participant). Further, there is a column identifier for if that row is for a coach or player.
CREATE TABLE Meeting_Data (
Meeting_ID int,
Player_ID int,
Coach_ID int,
field_id int
);
INSERT INTO Meeting_Data
VALUES (1,0,11,2),
(1,10,0,1),
(2,34,0,1),
(2,0,13,2),
(3,98,0,1),
(3,0,33,2),
(4,78,0,1),
(4,0,53,2)
;
What I'm trying to do is create a table that puts each Meeting on one row, and then puts the ID#s and Names of the people meeting. When I attempt this, I get one column to pull successfully and then one column of (null) values.
SELECT Meeting_ID,
Max(CASE
WHEN field_id = 1 THEN Player_ID
END) AS Player_ID,
Max(CASE
WHEN field_id = 2 THEN Coach_ID
END) AS Coach_ID,
Player_Names.Title as Player_Names,
Coach_Names.Title as Coach_Names
FROM Meeting_Data
LEFT JOIN Names Player_Names
ON Player_ID = Player_Names.ID
LEFT JOIN Names Coach_Names
ON Coach_ID = Coach_Names.ID
GROUP BY Meeting_ID
Which results in:
| Meeting_ID | Player_ID | Coach_ID | Player_Names | Coach_Names |
|------------|-----------|----------|--------------|-------------|
| 1 | 10 | 11 | Deb | (null) |
| 2 | 34 | 13 | Steph | (null) |
| 3 | 98 | 33 | Peter | (null) |
| 4 | 78 | 53 | Christine | (null) |
How about something like this (http://sqlfiddle.com/#!9/53d3c/52/0):
SELECT Meeting_ID, Player_ID, Coach_ID, Players.Title, Coaches.Title
FROM (
SELECT Meeting_ID,
MAX(Player_ID) as Player_ID,
MAX(Coach_ID) as Coach_ID
FROM Meeting_Data
GROUP BY Meeting_ID
) meeting
LEFT JOIN Names Players ON Players.ID = meeting.Player_ID
LEFT JOIN Names Coaches ON Coaches.ID = meeting.Coach_ID

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