I have the following data in a table, the column name is title:
Acqua Di Parma Blu Mediterraneo Arancia Di Capri Scented Water EDT
Acqua Di Parma Blu Mediterraneo Arancia
Acqua Di Parma Blu Mediterraneo Bergamotto Di Calabria
Acqua Di Parma Blu Mediterraneo Cipresso Di Toscana Scented Water EDT
Acqua di Parma Blu Mediterraneo fico di amalfi
Acqua Di Parma Blu Mediterraneo Fico di Amalfi Scented Water EDT
Acqua Di Parma Blu Mediterraneo Mirto di Panarea
Acqua Di Parma Blu Mediterraneo Mirto di Panarea Scented Water EDT
Acqua Di Parma Blu Meditteraneo Cipresso
Acqua Di Parma Colonia Assoluta Bath
Acqua Di Parma Colonia Assoluta
Acqua Di Parma Colonia Body Cream
Acqua Di Parma Colonia Body Cream Tube
Adidas Deep Energy
Adidas Dynamic Pulse
Adidas Fair Play
As you can see these are all variations of Acqua Di Parma Blu Mediterraneo and Adidas products
Is there a way to read the data, letter by letter, then when the next letter does not appear more than say 3 times, return what is before the letter change
Basically, I want to read this list and return only
Acqua Di Parma Blu Meditteraneo
Acqua Di Parma Colonia
Adidas Deep Energy
Adidas Dynamic Pulse
Adidas Fair Play
The whole table is about 70,000 rows all of similar data.
The table consists of row_id, title, category
Possible?
Many thanks
Darren
OK - this isnt pretty and not sure it's completely right but it's the closest i could get.
I created a separate table containing each group of substrings like this
create table subs as
select title,
substring_index(title, ' ',1) one,
substring_index(title, ' ',2) two,
substring_index(title, ' ',3) three,
substring_index(title, ' ',4) four,
substring_index(title, ' ',5) five,
substring_index(title, ' ',6) six,
substring_index(title, ' ',7) seven
from title;
and then created a query to check if a group by of one column was greater than 1 (ie not unique) and the group by of then next column was = 1 (i.e. unique) and that the previous column was a substring of the next, then just unioned together the result of each pair of columns and finally did a select distinct across the whole lot
select distinct brand from (
select * from
(select one brand, count(*) bcount
from subs
group by one) one,
(select two prod, count(*) pcount
from subs
group by two) two
where bcount > 1
and pcount=1
and locate(one.brand, two.prod)>0
union all
select * from
(select two brand, count(*) bcount
from subs
group by two) two,
(select three prod, count(*) pcount
from subs
group by three) three
where two.bcount > 1
and three.pcount=1
and locate(two.brand, three.prod)>0
union all
select * from
(select three brand, count(*) bcount
from subs
group by three) three,
(select four prod, count(*) pcount
from subs
group by four) four
where three.bcount > 1
and four.pcount=1
and locate(three.brand, four.prod)>0
union all
select * from
(select four brand, count(*) bcount
from subs
group by four) four,
(select five prod, count(*) pcount
from subs
group by five) five
where four.bcount > 1
and five.pcount=1
and locate(four.brand, five.prod)>0
union all
select * from
(select five brand, count(*) bcount
from subs
group by five) five,
(select six prod, count(*) pcount
from subs
group by six) six
where five.bcount > 1
and six.pcount=1
and locate(five.brand, six.prod)>0
union all
select * from
(select six brand, count(*) bcount
from subs
group by six) six,
(select seven prod, count(*) pcount
from subs
group by seven) seven
where six.bcount > 1
and seven.pcount=1
and locate(six.brand, seven.prod)>0) x
which results in the following
But it still has some problems as it shows both Aqua Di Parma Blu and Aqua Di Parma Medit.. in two lines instead of just once so it's not correct.
Related
I am making a join with two tables, tab_usuarios (users) and tab_enderecos (address).
tab_usuarios structure:
id_usuario
nome
usuario
1
Administrador
admin
2
Novo Usuário
teste
3
Joao Silva
jao
tab_enderecos structure:
id_endereco
id_usuario
cidade
uf
2
1
cidade
SP
20
2
Lorena
SP
22
2
Lorena
SP
24
3
Campinas
SP
28
4
Lorena
SP
I have this simple query which brings me the following result:
Select
u.id_usuario,
u.usuario,
u.nome,
e.id_endereco,
e.cidade,
e.uf
From
tab_usuarios u Left Join
tab_enderecos e On u.id_usuario = e.id_usuario
id_usuario
usuario
nome
id_endereco
cidade
uf
1
admin
Administrador
2
cidade
SP
2
user 2
Novo Usuário
22
Lorena
SP
2
user 2
Novo Usuário
20
Lorena
SP
3
jao
Joao Silva
24
Campinas
SP
4
teste
fabio
28
Lorena
SP
What I want is, for example, for id_usuario = 2, I only want to bring the id_endereco = 20, which is the first address that have been inserted on the database.
I tried with min and a couple others.
This should do it, assuming you have MySql 8.0 and not some ancient 5.x version:
SELECT *
FROM (
SELECT u.id_usuario, u.usuario, u.nome, e.id_endereco, e.cidade, e.uf,
row_number() over (partition by u.id_usuario order by e.id_endereco) rn
FROM tab_usuarios u
LEFT JOIN tab_enderecos e On u.id_usuario = e.id_usuario
) t
WHERE rn = 1
See it work here:
https://dbfiddle.uk/?rdbms=mysql_8.0&fiddle=c506baf8157f82390bb335d074e7614c
For a project I was asked to design a DB for a small Olympic games. This is the ER diagram I made for the DB.
For one of the required queries, I need to list the sport, event, name, country, and result(medal) for everyone. So far the only problem I am having is ranking(assigning GOLD, SILVER, or BRONZE) each of the results based only on others in the same event.
My query so far:
SELECT cy.countryname COUNTRY,
c.firstname || ' ' || c.lastname "COMPETITOR",
s.sportname,
e.eventname EVENT,
rs.result
FROM COUNTRY cy
JOIN COMPETITOR c ON cy.COUNTRYID = c.COUNTRYID
JOIN RESULT rs ON c.competitorid = rs.competitorid
JOIN EVENT e ON rs.eventid = e.eventid
JOIN SPORT s ON e.sportid = s.sportid
ORDER BY e.eventname, rs.result;
Produces:
UNITED STATES NORRIS HOLMWOOD SWIMMING 100 METER BUTTERFLY 49.82
ITALY LEANDRO ROCCO SWIMMING 100 METER BUTTERFLY 50.65
ARGENTINA ORFEO SILVA SWIMMING 100 METER BUTTERFLY 50.69
IRAN HAMUND NAMAD SWIMMING 100 METER BUTTERFLY 51.2
CHINA MU KWOK SWIMMING 100 METER BUTTERFLY 51.32
RUSSIA MITRODFAN KRUPIN SWIMMING 100 METER BUTTERFLY 52.01
ARGENTINA NICOLAO VARELA TRACK AND FIELD 100 METER DASH 9.76
ITALY STEFANO PAVONI TRACK AND FIELD 100 METER DASH 9.98
UNITED STATES ROBBY TURNBULL TRACK AND FIELD 100 METER DASH 10.1
RUSSIA IRINEY POLZIN TRACK AND FIELD 100 METER DASH 10.35
CHINA TU JIANG TRACK AND FIELD 100 METER DASH 10.54
IRAN SAKHR NAGI TRACK AND FIELD 100 METER DASH 10.56
UNITED STATES SCARLETT NOWELL SWIMMING 200 METER BACKSTROKE 116.32
IRAN MALIKA NEJEM SWIMMING 200 METER BACKSTROKE 116.88
etc...
How would I go about assigning each competitor a GOLD, SILVER, BRONZE, or NO MEDAL based only on the other results in the same event?
use two variables
SELECT cy.countryname COUNTRY, c.firstname || ' ' || c.lastname "COMPETITOR", s.sportname, e.eventname EVENT, rs.result,
if(#curGame !=s.sportname,#curRank :=0,#curRank) AS setrank, #curRank := #curRank + 1 as rank,#curGame :=s.sportname as game_name
FROM COUNTRY cy
JOIN COMPETITOR c ON cy.COUNTRYID = c.COUNTRYID
JOIN RESULT rs ON c.competitorid = rs.competitorid
JOIN EVENT e ON rs.eventid = e.eventid
JOIN SPORT s ON e.sportid = s.sportid,(SELECT #curRank := 0,#curGame := "") r
ORDER BY e.eventname, rs.result;
I have been struggling and would really appreciate some assistance:
I have two tables cars and rides
cars
car_id car_manuf car_model
1 Honda CRV
2 Honda Accord
3 Toyota Corolla
4 Toyota Camry
5 Ford Fusion
rides
ride_id car_id ride_destination
1 3 Boston
2 5 New York
3 5 Washington DC
4 1 California
5 2 Dallas
6 5 Canada
I would like to count the number of rides by each car type which will have the combination of car_manuf and car_model and should be sorted from most to fewest number of rides.
Output should be:
CarType-NumberofRides
Honda_CRV-1
Honda_Accord-1
Toyota_Corolla-1
Toyota_Camry-0
Ford_Fusion-3
Sorted output with most-few rides
CarType-NumberofRides
Toyota_Camry-0
Honda_Accord-1
Toyota_Corolla-1
Honda_CRV-1
Ford_Fusion-3
mycode:
select
c.car_manuf + '_' + c.car_model AS 'Car Type',
(select count(*) from rides r where r.car_id = c.car_id) AS 'Number of Rides'
from cars c;
I am kinda stuck here and not sure which direction I should go in regards to getting the correct output.
You have to use GROUP BY and an ORDER BY when COUNTing the occurences. I use CONCAT to concatenate the strings instead of a + sign. Makes clearer what is going on, and is not mistaken as an arithmetic operation.
SELECT CONCAT(c.car_manuf, '_', c.car_model) AS CarType, COUNT(r.car_id) AS NumberOfRides
FROM rides r
LEFT JOIN cars c ON (r.car_id = c.car_id)
GROUP BY CarType
ORDER BY NumberOfRides ASC
However this omits the 0 occurences.
If you want to see the 0s as well swap the table order to:
SELECT CONCAT(c.car_manuf, '_', c.car_model) AS CarType, COUNT(r.car_id) AS NumberOfRides
FROM cars c
LEFT JOIN rides r ON (r.car_id = c.car_id)
GROUP BY CarType
ORDER BY NumberOfRides ASC
I have a table that lists food types, I would like a run a query to return a maximum of 12 foods but with no more than 3 from each category. Can I do this in one query?
category food tastyFactor id
seafood fish 100 1
seafood prawns 150 2
seafood crab 50 3
seafood oysters 300 4
meat chicken 20 5
meat pork 100 6
meat lamb 40 7
meat beef 50 8
vegetables carrot 10 9
vegetables cabbage 300 10
vegetables potato 75 11
vegetables parsnip 500 12
The foods should be ordered by tastyFactor (the lowest number the earlier in the result set they should appear).
In my example the results should be:
carrot
chicken
lamb
beef
crab
potato
fish
prawns
cabbage
You can use UNION to combine multiple queries with the same content:
SELECT food FROM (
(SELECT category, food, tastyfactor, id FROM table
WHERE category = 'seafood' LIMIT 3)
UNION
(SELECT category, food, tastyfactor, id FROM table
WHERE category = 'meat' LIMIT 3)
UNION
(SELECT category, food, tastyfactor, id FROM table
WHERE category = 'vegetables' LIMIT 3)
) AS food_from_cateogry ORDER BY tastyfactor
Assuming you don't know the number of categories in advance, you can still do the query. You need to start by enumerating the values within each category. Although you can use variables, I'll opt for the correlated subquery approach for the enumeration:
select ft.food
from (select ft.*,
(select count(*)
from FoodTypes ft2
where ft2.category = ft.category and
(ft2.tastyFactor < ft.tastyFactor or
ft2.tastyFactor = ft.tastyFactor and ft2.id <= ft.id
)
) as cat_seqnum
from FoodTypes ft
) ft
where cat_seqnum <= 3
order by TastyFactor
limit 12;
SELECT x.food
FROM my_table x
JOIN my_table y
ON y.category = x.category
AND y.tastyfactor <= x.tastyfactor
GROUP
BY x.category
, x.food
HAVING COUNT(*) <= 3
ORDER
BY x.tastyfactor
, x.food;
Note, you may want to think a little more about how to handle ties.
Can be done using a combo of GROUP_CONCAT and FIND_IN_SET. For large set I i imagine the processing will degrade, but it fairly straightforward for smaller data.
SELECT a.food
,b.category
,find_in_set(a.food, foods) ranking
FROM food a
INNER JOIN (
SELECT category,
GROUP_CONCAT(food ORDER BY tastyFactor DESC) foods
FROM food
GROUP BY category
) b ON a.category = b.category
WHERE FIND_IN_SET(a.food, foods) <= 3
ORDER BY category
,ranking ASC
Fiddle
I have two tables: "series" and "product"
"series" holds the names of series of books, "product" has the details of individual book titles.
So something like this:
Series Table:
id series_name series_description
1 Lord of the Rings Trilogy of fantasy books recently made into film
2 A Song of Ice and Fire Epic series of novels currently showing on HBO
3 Harry Potter Famous Children's book series also loved by adults
Product Table:
id product_name series_id author etc...
1 Fellowship of the Ring 1 JRR Tolkien
2 The Two Towers 1 JRR Tolkien
3 Return of the King 1 JRR Tolkien
4 A Game of Thrones 2 George R R Martin
5 A Clash of Kings 2 George R R Martin
6 A Storm of Swords 2 George R R Martin
7 A Feast for Crows 2 George R R Martin
8 A Dance with Dragons 2 George R R Martin
9 Harry Potter and the... 3 JK Rowling
etc.
I want to SELECT * FROM series, and COUNT(*) FROM product so that the query returns a table containing the series info, with the number of products in the database corresponding to each series appended as the last column of the table. I'd also like to do this by genre, so there is an additional WHERE clause in there somewhere. It would look something like this, if selecting "Fantasy and Magic" as the genre:
id series_name series_description number_of_products
1 Lord of the Rings Trilogy of Fantasy... 3
2 A Song of Ice and Fire Epic Series of Novels... 5
3 Harry Potter Famous Children's book... 7
I think I may need a LEFT JOIN but my best attempts so far have been in vein.
This is what I have so far, but I think it's probably totally wrong.
SELECT series.id,
series.series_name,
series.publisher_id,
series.description,
series.image,
COUNT (product.*) as nRows
FROM series
LEFT OUTER JOIN product
ON series.id = product.series_id
WHERE series.genre = 'Fantasy and Magic'
GROUP BY ... (do I need a GROUP BY?)
Any help at all would be really appreciated. Thanks in advance!
Almost there. Try this.
SELECT series.id,
series.series_name,
series.publisher_id,
series.description,
series.image,
COUNT (product.id) as nRows
FROM series
LEFT OUTER JOIN product
ON series.id = product.series_id
WHERE series.genre = 'Fantasy and Magic'
GROUP BY series.id,
series.series_name,
series.publisher_id,
series.description,
series.image
Wouldn't this help;
select s.id,
s.series_name,
s.series_description,
(select count(*) from Products p where p.series_id = s.id) number_of_products
from Series s