MySQL row number - mysql

Say I have a MySQL query, for example:
SELECT id, name, surname FROM employees ORDER BY id
The result woud be:
id name surname
1 Peter Smith
2 John Banjo
...
1384 Will Levenstein
While this is an ordered query, I can always assume (as long as I don't change the table) that John Banjo will come out second.
Now what if my query was
SELECT id, name, surname FROM employees WHERE name = 'John' AND surname = 'Banjo'
Could I somehow get what the row number would be in the first query?
I'm trying to do this in a much more complicated, but always ordered query, is there any way to archieve this?

SELECT x.id, x.name, x.surname, x.rownum
FROM (
SELECT #rownum:=#rownum+1 rownum, t.*
FROM (SELECT #rownum:=0) r, employees t
ORDER BY Id
) x
WHERE x.name = 'John'
AND x.surname = 'Banjo'

Related

MySQL - SELECT Most occuring value (with several same occurrences)

I have been looking for a way to do a MySQL select to get all the most occuring values. All the solutions i have found where with using LIMIT 1, but this doesn't help if there are more than one value that occur the same amount of times. E.g:
customer
ID
FirstName
1
Bob
2
Tom
3
Bob
4
Robert
5
Tom
6
Timothy
The Select for most occuring FirstNames should result in:
FirstName
Bob
Tom
Since both occur twice.
I have tried the following:
SELECT FirstName FROM (
SELECT FirstName, COUNT(FirstName) as counter FROM customer
GROUP BY FirstName
HAVING counter = MAX(counter)
) s
But this doesn't seem to work, i would really appreciate a nudge in the right direction.
There can be different ways for doing this
you can try
1st
SELECT FIRSTNAME
FROM customer
GROUP BY FirstName Having count(FirstName) = (
SELECT COUNT(FirstName) FROM customer GROUP BY FirstName ORDER BY 1
DESC LIMIT 1);
2nd
with cte as
(
SELECT COUNT(FirstName) MaxCounter
FROM customer
Group By FirstName ORDER BY COUNT(FirstName) DESC LIMIT 1
)
SELECT c.FirstName
From customer c
Group BY FirstName
HAVING COUNT(FirstName) = (SELECT MaxCounter FROM cte)

Is it possible to output the result of a union of two subqueries in alternating order?

Lets say I have two subqueries in a UNION statement like so:
(
SELECT *
FROM users
ORDER BY registration_date
)
UNION ALL
(
SELECT *
FROM food
ORDER BY popularity
)
The output is the following:
Bob
Alice
Steve
Mark
...
Sandwich
Pizza
Burger
Fries
...
Is it possible to output them in an alternating fashion, such that the output is:
Bob
Sandwich
Alice
Pizza
Steve
Burger
Mark
Fries
...
Each query output is thousands of items.
You could use row_number() if you are running MySQL 8.0:
(select name, 1 src, row_number() over(order by registration_date) rn from users)
union all
(select name, 2, row_number() over(order by popularity) from food)
order by rn, src
In each unioned subquery, we use row_number() to rank the records, and add another column, called src to identify from which table the record comes from.
Then all that is left to do is order by the assigned row_number(), using the additional column to alternate the records.
Note that I modified your query to enumerate the columns being selected in the subqueries; select * is generally not a good practice, especially with union all, which requires both datasets to have the same number of columns (with equivalent datatypes).
Just in case you are not using MySQL 8+, you can still simulate ROW_NUMBER using a correlated count query:
(
SELECT 1 AS idx, name,
(SELECT COUNT(*) FROM users u2 WHERE u2.registration_date < u1.registration_date) rn
FROM users u1
)
UNION ALL
(
SELECT 2, name,
(SELECT COUNT(*) FROM food f2 WHERE f2.popularity < f1.popularity) rn
FROM food f1
)
ORDER BY
rn,
idx;
DECLARE #id INT;
SET #id :=0;
SELECT id,t.* FROM(
SELECT u.*,(#id:=#id+1) AS id
FROM users u
ORDER BY registration_date
)
UNION ALL
(
SELECT f.*,(#id:=#id+2) AS id
FROM food f
ORDER BY popularity
)t
ORDER BY id;

Hierarchy based on three tables

I would like to have rows like a single table like the following
id name parentId
My current tables are (keys between them are foreign keys)
category
id name
which is the parent of all
and
subcategory
id name catId
and the last table which is activity
activity
id name subcatId
For the parentId of category table, it would be nothing as category is the parent of all
My attempt so far have been unsuccessful
Sample Data
category
C-1 HR null
C-2 Development null
subcategory
SC-1 Hiring C-1
SC-2 Admin C-1
SC-3 Developer C-2
activity
A-1 College Hiring SC-1
A-2 Job Fair SC-1
A-3 Java Development SC-3
Result Needed
1 HR null
2 Development null
3 Hiring C-1
4 Admin C-1
5 Developer C-2
6 College SC-1
7 Job Fair SC-1
8 Java Development SC-3
I hope it is clearer. If you need any further information, please let me know
Thanks
my attempt on 2 tables
select name
from (
select c.name
from category c
union all
select b.name
from subcategory b
inner join category ca
on ca.id = b.parentId
)
I get an error saying
Every derived table must have its own alias
Do I need to add the following lines to my query
start with parent_id is null
connect by prior id = parent_id
Try something like this:
SELECT #id := #id + 1 AS id, name, parent_id
FROM ( SELECT name, NULL AS parent_id FROM category
UNION ALL
SELECT id, name, catId FROM subcategory
UNION ALL
SELECT id, name, parentId FROM activity
) q,
( SELECT #id := 0 ) w;
Used UNION ALL to concatenate the results from multiple queries.
In UNION the column names of the first query is used as column names of the result set.
Used variable #id and the assignment operator := to generate the calculated values of the column ID.
Be advised: If you use LIMIT or OFFSET, the values of column id would not be coherent.
Actually, like this should solve your problem:
select name
from (
select c.name
from category c
union all
select b.name
from subcategory b
inner join category ca
on ca.id = b.parentId
) A -- alias is required for sub-query.
You can set anything as alias provided that it won't conflict with some of MySQL reserved word. You can set like this as well ) AS A.
For you situation, I don't think it's necessary to do sub-query or inner join. If you really want the result to be like that you can just use union all:
SELECT name,'' as ID from category
UNION ALL
SELECT name,catId FROM subcategory
UNION ALL
SELECT name,subcatId FROM activity;

Grouping in Max query

I have the following query which is working fine except for the fact that it is not grouping as I wish:
SELECT
oee_main_interim.id,
oee_main_interim.NAME,
oee_main_interim.S_TYPE
FROM
oee_main_interim
WHERE
oee_main_interim.S_TYPE <>0
GROUP BY
oee_main_interim.id, oee_main_interim.NAME
HAVING
oee_main_interim.id= max(oee_main_interim.id)
All 3 fields are INT types. The query is returning the max values of id by not grouping by NAME, instead it is listing more than one NAME. What I want is simply: Max ID, the corresponding NAME and the corresponding S_TYPE. So my output should be something like this:
ID NAME S_TYPE
1234 1 2
1345 2 1
1456 3 2
1567 4 2
with ID being the max id of the table for each NAME ...
My raw data in table oee_main_interim is as follows:
So all I want is choose the max ID for each NAME and show its relevant S_TYPE (as shown above) and where S_TYPE <>0.
My full table with all columns is as follows:
This query, using a derived table, will give you the max id for each name, along with its s_type:
Select
oee_main_interim.id,
oee_main_interim.NAME,
oee_main_interim.S_TYPE
From
oee_main_interim
Join
(
select max(id) max_id, name from oee_main_interim group by name
) a on a.name = oee_main_interim.name and a.max_id = oee_main_interim.id
Where
oee_main_interim.S_TYPE <> 0
Or you could use a correlated subquery:
Select
id, NAME, S_TYPE
From
oee_main_interim o1
Where
S_TYPE <> 0
And id = (select max(id) from oee_main_interim o2 where o1.name = o2.name);

Mysql: which pizza prefer client

I have table with this data :
1. John | seafood pizza
2. Mike | pepperoni pizza
3. Mike | pepperoni pizza
4. John | original pizza
5. Mike | original pizza
6. John | seafood pizza
7. John | pepperoni pizza
....
How can I write a query that give me result such this:
John | seafood pizza
Mike | pepperoni pizza
If client have same quantity for many pizzas, the result may be any pizza's name.
Let's take it step by step
the following query will give you number of times each client ordered each kind of pizza
SELECT name, pizza, COUNT(*) AS cnt
FROM yourTable
GROUP BY name, pizza
So how do we get the most often ordered pizza from that? We must first know, what is the highest number of pizza ordered by each client
SELECT name, MAX(cnt) AS cnt FROM (
SELECT name, pizza, COUNT(*) AS cnt
FROM yourTable
GROUP BY name, pizza
) AS subquery GROUP BY name
then use this number to select actual pizza name
SELECT name, pizza, COUNT(*) AS cnt
FROM yourTable AS t
CROSS JOIN (
SELECT name, MAX(cnt) AS cnt FROM (
SELECT name, pizza, COUNT(*) AS cnt
FROM yourTable
GROUP BY name, pizza
) AS subquery GROUP BY name
) AS sq
USING(name,cnt)
GROUP BY name, pizza
I'd go with grouping the counts by user and pizza then using this as a datasource for a query which finds the groupwise maximum (using the max concat trick). It's not hard:
SELECT user, SUBSTRING(MAX(CONCAT(LPAD(freq, 6, '0'),pizza)),7)
FROM
(SELECT user, pizza, COUNT(*) AS freq
FROM user_likes
GROUP BY user, pizza) ilv
GROUP BY user
Let's have a simple solution :
First of all, we have two columns,name and food.
You can list of favorite customer's food easily :
CREATE TEMPORARY TABLE tbltemp AS (
SELECT name, food, COUNT( * ) c
FROM food
GROUP BY name, food
);
Now we have all of foods by count.
Then you can order it by count descending :
SELECT *
FROM tbltemp
ORDER BY c DESC
Now you have a list that describes your customer's favorite.
UPDATE :
Instead of second query ,replace this one :
SELECT tbl1 . *
FROM (
SELECT name, food, COUNT( * ) c
FROM food
GROUP BY name, food
) AS tbl1, (
SELECT name, food, COUNT( * ) c
FROM food
GROUP BY name, food
) AS tbl2
WHERE tbl1.c = tbl2.c
AND tbl2.name = tbl1.name
AND tbl2.food = tbl1.food
AND tbl1.c = (
SELECT c
FROM tbltemp
ORDER BY c DESC
LIMIT 1 )
This query result is your question goal.