Split N-Values to N-rows using MySQL Query [duplicate] - mysql

This question already has an answer here:
Split Comma separated Values in Column MYSQL
(1 answer)
Closed 5 years ago.
I have the table training, I want to split Training_name Column values to multiple Rows:
SLNO Category Training_name
1 A 1,5,9,15,12,16
2 B 2,6,10,17
3 C 1,3,7,19,14,18
I used below Query but using this Query i can only split to 2 Rows only?
SELECT training.SLNO,training.CATEGORY, SubString_Index(training.TRAINING_NAME, ',', 1) AS TRAINING_NAME FROM training UNION ALL SELECT training.SLNO,training.CATEGORY, SubString_Index(training.TRAINING_NAME, ',', -1) FROM training
i am trying to get the table as given below,Please help me out
SLNO Category Training_name
1 A 1
1 A 5
1 A 9
1 A 15
1 A 12
1 A 16
2 B 2
2 B 6
2 B 10
2 B 17
3 C 1
3 C 3
3 C 7
3 C 19
3 C 14
3 C 18

Here is an option which will work well if every training name entry has two values separated by a single comma.
SELECT
PARENT_SLNO,
RNO,
TRAINING_CATEGORY,
SUBSTRING_INDEX(TRAINING_NAME, ',', 1) AS TRAINING_NAME
FROM yourTable
UNION ALL
SELECT
PARENT_SLNO,
RNO,
TRAINING_CATEGORY,
SUBSTRING_INDEX(TRAINING_NAME, ',', -1)
FROM yourTable
If you want to convert your entire table, then you could select the above query into a new table, delete the old one, then rename the new one. If your CSV data could have a varying number of commas then my query would need to be modified, but the general approach could remain the same.

Related

Make a query to select a value from one column that is combined with all the values from another column

Imagine I have the following tables:
Numbers PK
1
2
3
4
5
6
7
8
9
10
Numbers FK 1
Numbers FK 2
1
1
2
1
3
1
4
1
5
1
6
1
7
1
8
1
9
1
10
1
8
8
10
4
7
3
4
9
1
6
3
9
4
6
5
6
I have the following tables: "Numbers PK" as Primary key and another 2 tables that are related one with each other that are foreign keys of Numbers.
I am trying to make a query to select the number(s) from the table "NumbersFK2" that are related with all the numbers of "Numbers PK".
As you can see in this example the solution would be 1 as 1 is related with 1-10 in the tables "Numbers FK1" and "Numbers FK2"
I have tried to solve and after some days I need some help as I don't know how could I do it. I appreciate the help. Thanks
We use dense_rank() to count the Numbers_PK in case they're not consecutive. Then we left join, group by and count(distinct Numbers_PK).
with t3 as (
select Numbers_PK
,dense_rank() over(order by Numbers_PK) as dns_rnk
from t
)
select Numbers_FK_2
from t3 left join t2 on t2.Numbers_FK_1 = t3.Numbers_PK
group by Numbers_FK_2
having count(distinct Numbers_PK) = max(dns_rnk)
Numbers_FK_2
1
Fiddle

How to get the average number of cities crossed [duplicate]

This question already has an answer here:
How to write these complex MySQL queries?
(1 answer)
Closed 1 year ago.
I am a beginner at databases. I need to write some SQL queries.
The tables are:
Expedition(id, number, id_captain, id_ship, id_heros)
City(id, name)
Heros(id, family_name, first_name)
Step(id, index, id_expedition, id_city)
sample data :
'Table expedition'
id
number
id_captain
id_ship
id_hero
1
1
1
10
8
2
2
2
1
5
3
3
1
8
3
4
4
10
9
6
5
5
5
7
4
6
6
6
5
4
7
7
7
3
7
8
8
8
2
8
9
9
9
1
3
10
10
1
4
2
11
11
6
3
1
12
12
8
6
1
13
13
5
8
6
14
14
4
9
9
15
15
3
10
4
16
16
10
2
2
17
17
9
3
3
18
18
8
7
7
19
19
9
8
10
20
20
7
2
2
table 'heros'
id
family_name
first_name
1
familyname1
firstname1
2
familyname2
firstname2
3
familyname3
firstname3
4
familyname4
firstname4
5
familyname5
firstname5
6
familyname6
firstname6
7
familyname7
firstname7
8
familyname8
firstname8
9
familyname9
firstname9
10
familyname10
firstname10
query1: The family (based on the family name) with the least travelling (the fewest cities different crossings).
i have done this for the first query:
select expedition.id, id_hero, heros.family_name as Famille_expedition, count(distinct id_city) as city_count
from expedition, step, heros
where expedition.id=step.id and expedition.id_hero=heros.id
group by id_hero
having city_count =
(select count(distinct id_city) as min_city_count
from expedition, step
where expedition.id=step.id
group by id_hero
order by min_city_count asc
limit 1);
query2: The average of cities crossed by an expedition
I have no idea how to answer the second one.
Well, first ask yourself what information do you need to answer your question?
From your question, I'd say the average number of crossings is just the sum of all entries in the steps table, divided by the number of expeditions, since in each step, one city is visited and the average of all visits is what you are looking for:
SELECT (
(SELECT COUNT(s.id_city)
FROM step AS s) /
(SELECT COUNT(e.id)
FROM expedition AS e) ) AS total_average__cities
That being said, it depends on how exactly you define number of cities and crossing. Imagine the following example data for the table step:
id
idx
id_expedition
id_city
1
1
1
1
2
2
1
5
3
3
1
3
4
1
2
5
5
2
2
9
6
1
3
8
7
2
3
5
8
3
3
9
9
4
3
5
10
5
3
8
The table lists the steps for three expeditions. Expedition 1 goes from one city via another to a third. Expedition 2 goes directly from one city to another. And expedition 3 goes through several cities and visits one city twice along the way and also returns to the city that it started in.
The average number of cities over all these steps is (3 + 2 + 5 [cities in all steps]) / 3 [expeditions] = 3.3333. That is the result of the above query.
Now, if you define number of cities as meaning unique cities for each expedition, expedition 3 only visits 3 cities instead of 5. Then your average calculates as (3 + 2 + 3 [unique cities/expedition in all steps]) / 3 [expeditions] = 2.6666. The according query needs to count the distinct cities within each expedition before building the average:
SELECT (
(SELECT SUM(cnt) FROM (SELECT COUNT(DISTINCT s.id_city) AS cnt
FROM step AS s
GROUP BY s.id_expedition) t) /
(SELECT COUNT(e.id)
FROM expedition AS e) ) AS total_average__cities
Now, if you define crossing as only covering cities along the way, expedition 1 only crosses 1 city and expedition 2 crosses none at all.
Then your query also needs to look differently. You need to filter the all cities to exclude the first and the last for each expedition. The subquery could look like this:
SELECT s.* FROM step s
JOIN ( SELECT id_expedition,
MAX(idx) AS max_idx,
MIN(idx) AS min_idx
FROM step s
GROUP BY id_expedition) minmax
ON s.id_expedition = minmax.id_expedition
AND s.idx > minmax.min_idx
AND s.idx < minmax.max_idx
So for the case that you want the number of cities crossed excluding start and stop, your average would be computed as (1 + 0 + 3 [intermediate cities in all steps]) / 3 [expeditions] = 1.3333. The according query would be
SELECT (
(SELECT COUNT(s.id_city)
FROM step s
JOIN ( SELECT id_expedition,
MAX(idx) as max_idx,
MIN(idx) as min_idx
FROM step s
GROUP BY id_expedition) minmax
ON s.id_expedition = minmax.id_expedition
AND s.idx > minmax.min_idx
AND s.idx < minmax.max_idx) /
(SELECT COUNT(e.id)
FROM expedition AS e) ) AS total_average__cities
Finally, in case you want to both exclude start and stop and only want to count unique cities, your average would be computed as (1 + 0 + 2 [unique intermediate cities in all steps]) / 3 [expeditions] = 1. The following query combines the two approaches from above:
SELECT (
(SELECT SUM(cnt) FROM (SELECT COUNT(DISTINCT id_city) AS cnt
FROM step s
JOIN ( SELECT id_expedition,
MAX(idx) AS max_idx,
MIN(idx) AS min_idx
FROM step s
GROUP BY id_expedition) minmax
ON s.id_expedition = minmax.id_expedition
AND s.idx > minmax.min_idx
AND s.idx < minmax.max_idx
GROUP BY s.id_expedition) t) /
(SELECT COUNT(e.id)
FROM expedition AS e) ) AS total_average_cities
You can test all these queries in this db<>fiddle.

Find the lowest value of every row of selected columns

As the result of the query, I want to get all rows (Drivers), order by the drivers who got most series wins.
If a driver has won 4 tacks at least one or more times but failed to win the remaining track at least once, his series count is 0.
Driver Table
ID|Name| .........
1 A
2 B
3 C
4 D
Tracks Table
TID |FK|Track1_Wins|Track2_Wins| Track3_Wins|Track4_Wins|Track5_Wins|
1 1 5 6 3 2 4
2 2 2 4 0 5 3
3 3 6 3 9 4 7
4 4 5 8 2 4 1
My code sample
SELECT `Drivers`.`Name`, LEAST(`Track1_Wins`, `Track2_Wins`, `Track3_Wins`, `Track4_Wins`, `TRACK5_Wins`) AS Series
FROM `Drivers`, `Tracks`
ORDER BY Series DESC;
Accidently I got part expected output when I use WHERE with Driver ID
SELECT `Drivers`.`Name`, LEAST(`Track1_Wins`, `Track2_Wins`, `Track3_Wins`, `Track4_Wins`, `TRACK5_Wins`) AS Series FROM `Drivers`, `Tracks` WHERE `Drivers`.`ID` = 2 ORDER BY Series DESC;
It will give the expected result but with Same Driver Name as expected
B 3
B 2
B 1
B 0
My expected output is
Name | Series
C 3
A 2
D 1
B 0
Run this,
SELECT d.`Name`,
LEAST(`Track1_Wins`, `Track2_Wins`, `Track3_Wins`, `Track4_Wins`, `TRACK5_Wins`) AS Series
FROM `Drivers` d INNER JOIN `Tracks` t
ON t.`FK` = d.`ID`
ORDER BY Series DESC;
This returns the user name associated with the FK. Also, try to use kebab_case and lower case for all your column and table name. Makes it much easier to run the code

Sum within a column given two or more conditions in MySQL

In MySQL, I am trying to sum values in a column given certain conditions. I have an example of some data below
Team Season Mth Stat
A 1 1 4
A 1 1 4
A 1 2 7
A 1 2 9
B 1 1 6
B 1 1 6
B 1 2 6
B 1 2 9
C 1 1 1
C 1 1 3
C 1 2 3
C 1 2 6
But I need the output to show up as
Team Season Mth Stat
A 1 1 8
A 1 2 16
B 1 1 12
B 1 2 15
C 1 1 4
C 1 2 9
So the Stat column is now the sum of the cells such that Match, Season, and Team are all the same. I have the code below. I see a lot of answers that use 'case' but that seems to be given logical operators that are not equal to each other. When I do it below, now it doesn't recognise the table where the columns are coming from. I do have a inner joins but the data itself is from one table. I get another error as well on the sum function because it requires one argument.
select
Team
,Season
,Match
--this is where I get lost-----------
sum(
select
Stat
From
table
Where
Mth=Mth
AND Season=Season
AND Team=Team
)
--end of getting lost----------------
FROM
table
Where
Season IN (1,2)
GROUP BY
Team
,Season
,Mth
Order BY
Team ASC
Edit:
It turns out I need to use GROUP BY as the comments suggest. So I am not summing within a table, but I sum the variable given the Group By parameters.
Unless I'm missing something, it's simply:
SELECT Team
,Season
,Match
,Sum(Stat)
FROM table
GROUP BY
Team
,Season
,Match
It's simple as this:
SELECT Team,
Season,
Match,
SUM(Stat)
FROM Table
WHERE Season IN (1,2)
GROUP BY Team,
Season,
Match
ORDER BY Team ASC
Please look at the SQL Fiddle example.

mySql - Select but don't show duplicates of specific row

I need to SELECT from a db and don't show rows that are identical in SOME rows (or actually hide the rows that are identical to eachother except 1 item...)
Let's give an example:
ID C1 C2 C3
1 3 3 4
1 5 5 4
1 2 3 4
1 6 5 4
1 2 3 4
After SELECT i want:
ID C1 C2 C3
1 X 3 4
1 X 5 4
where "X" has no importance...i have to show that column but i don't care which one is shown.
Is this possible with a simple SELECT query?
To sum up, if i ask the question regarding this specific example, What can i do to SELECT from that table and show only one of the rows if it has identical duplicates in ID, C2 and C3?
SIDENOTE: this MYSQL: SELECT Method - but don't show duplicates / GROUP or DISTINCT? doesn't help.
Have you tried GROUP BY?
SELECT Id, MAX(C1), C2, C3
FROM SomeTable
GROUP BY Id, C2, C3
Since you don't care about C1, in this query, I get the largest C1 value.