mysql condition in a select - mysql

My table:
id | elite | pos
1 | 0 | 9
2 | 1 | 8
3 | 0 | 7
4 | 1 | 6
5 | 0 | 5
6 | 1 | 4
7 | 0 | 3
8 | 1 | 2
9 | 0 | 1
10 | 1 | 0
I have this simple query
SELECT id, elite FROM tbl LIMIT 0, 5 ORDER BY pos DESC
It will return the id 1 2 3 4 5. Over time, these values were to change. The result must have always a count of 5, however if on the result there are at least one id with an elite >= 1, the result must not contain any more id with an elite having the 1 value. So the result must not contain id having more than one elite >= 1.
Is this possible within a query?

You can use UNION to combine two queries, like so:
(SELECT * FROM tbl WHERE elite = 1 LIMIT 1)
UNION
(SELECT * FROM tbl WHERE elite = 0)
ORDER BY pos DESC LIMIT 5
It will give the results you need.
Check out Mysql reference for UNIONs

Related

Pagination in MySQL with JOINed ORDER clause

Having some trouble with paginating a dataset which is built by querying a joined table.
My product table looks like this:
id | sort_order
-----------------
1 | 5
2 | 4
3 | 0
4 | 0
5 | 4
...
and my joined stock table looks like this:
id | product_id | start_date
----------------------------
1 | 1 | 2018-12-14
2 | 1 | 2019-01-28
3 | 2 | 2018-12-26
4 | 3 | 2018-12-28
5 | 4 | 2019-01-12
6 | 4 | 2019-01-14
7 | 5 | 2020-01-10
...
I would like to paginate my list of products, however, I would like to sort it as follows:
Firstly, by sort_order
Secondly, by the earliest start_date associated to it.
I initially started with cursor pagination, but this was resulting in duplicate results, although the total number of pages (after cursoring to the end) was correct - this meant that there must have been missing rows which were never fetched.
I then resorted to page based pagination (which would also be fine for now), but this is resulting in duplication also, and a huge number of pages.
I'm quite stuck as to how to continue with this.
My offset-based pagination SQL (generated by Sequelize) is below:
SELECT
`Product`.`id` AS `id`,
`Product`.`sort_order` AS `sortOrder`,
`availability`.`id` AS `availability.id`,
`availability`.`product_id` AS `availability.productId`,
`availability`.`start_date` AS `availability.startDate`
FROM
`product` AS `Product`
LEFT OUTER JOIN `stock` AS `availability`
ON `Product`.`id` = `availability`.`productId`
ORDER BY
sort_order = 0,
sort_order
LIMIT 0, 10
With the dataset above, I would hope for the following:
id | sortOrder | `availability.id` | `startDate`
--------------------------------------------------
1 | 5 | 1 | 2018-12-14
2 | 4 | 3 | 2018-12-26
5 | 4 | 7 | 2020-01-10
3 | 0 | 4 | 2018-12-28
4 | 0 | 5 | 2019-01-12
You're getting duplication because you're JOINing to a table which has multiple values per product_id. You need to restrict that to one value, and based on your sort criteria that should be the values associated with the minimum start_date. You can do that with a subquery for the JOIN table:
SELECT
`Product`.`id` AS `id`,
`Product`.`sort_order` AS `sortOrder`,
`availability`.`id` AS `availability.id`,
`availability`.`product_id` AS `availability.productId`,
`availability`.`start_date` AS `availability.start_date`
FROM
`product` AS `Product`
LEFT JOIN (SELECT id, product_id, start_date
FROM`stock` s
WHERE start_date = (SELECT MIN(start_date)
FROM stock s1
WHERE s1.product_id = s.product_id)
) AS `availability`
ON `Product`.`id` = `availability`.`product_id`
ORDER BY
sort_order = 0,
sort_order,
availability.start_date
LIMIT 0, 10
Output for your sample data:
id sortOrder availability.id availability.productId availability.start_date
1 5 1 1 2018-12-14
2 4 3 2 2018-12-26
5 4 7 5 2020-01-10
3 0 4 3 2018-12-28
4 0 5 4 2019-01-12
Demo on SQLFiddle

MqSql - fetch rows which employee has maximum complaint severity level

I am dealing with a table Employee Complaint which has columns EmployeeId ComplaintSeverity and ComplaintByUser. ComplaintSeverity has four level 0,1,2, and 3.
So the table will look like this ,Example
ComplaintId|EmployeeId|ComplaintSeverity|usr_id
-----------------------------------
1 | 1 | 0 | 3
2 | 2 | 1 | 4
3 | 3 | 0 | 5
4 | 1 | 2 | 4
5 | 4 | 1 | 5
6 | 2 | 2 | 2
7 | 2 | 2 | 4
Any user can complaint employee with any of these level
When client search with severitylevel as 0,
The row should fetch as
ComplaintId|EmployeeId|ComplaintSeverity
----------------------------
3 | 3 | 0
for severitylevel as 1,
ComplaintId|EmployeeId|ComplaintSeverity
----------------------------
5 | 4 | 1
for severitylevel as 2,
ComplaintId|EmployeeId|ComplaintSeverity
----------------------------
4 | 1 | 2
6 | 2 | 2
EmployeeId 1 has been complained by 2 user with severitylevel 0,2 but his highest severity level is 2. so while searching for 0 level, 1 should not be displayed.
Can anyone help me?
The question was edited after the previous answer was submitted. The following would therefore be more accurate.
SELECT x.*
FROM my_table x
JOIN
( SELECT employeeid
, MAX(complaintseverity) severity
FROM my_table
GROUP
BY employeeid
) y
ON y.employeeid = x.employeeid
AND y.severity = x.complaintseverity
WHERE complaintseverity = 0 -- optional line
ORDER
BY employeeid;
You can try following query.
SELECT *
FROM
(
SELECT cs.`EmployeeId`, MAX(cs.`ComplaintSeverity`) severity
FROM ComplaintSeverity cs
GROUP BY cs.`EmployeeId`
) csdata
WHERE csdata.severity=1
Replace 1 with the severity level you want.

MySQL subtracting successive rows in same column

My question is similar to this SO post however the difference is that I do not have a sequential ID column.
I have a table in the following form
ID | length
0 | 5
0 | 7
0 | 10
1 | 3
1 | 8
1 | 12
2 | 1
2 | 2
2 | 4
2 | 5
and I want to get the difference between successive rows in the length column grouped by the ID. So it should give
ID | length | difference
0 | 5 | NULL
0 | 7 | 2
0 | 10 | 3
1 | 3 | NULL
1 | 8 | 5
1 | 12 | 4
2 | 1 | NULL
2 | 2 | 1
2 | 4 | 2
2 | 5 | 1
I'm not sure how to go about doing this. I tried giving each ID a separate ID that is sequential, but it turned out to be way to complicated and I could not get it to work. Can someone suggest a better way of doing it?
Assuming (id,length) is UNIQUE...
SELECT x.*
, x.length - MAX(y.length) diff
FROM my_table x
LEFT
JOIN my_table y
ON y.id = x.id
AND y.length < x.length
GROUP
BY x.id
, x.length;
select a.id, a.length, b.length, b.length - a.length as difference
from mytable a, mytable b
where a.id=b.id
and b.length = (select min(length) from mytable where id=a.id and length > a.length)

Sub groups within Group By query in mysql

My table is as follows
a | b
--|--
0 | 5
1 | 6
2 | 7
3 | 7
4 | 7
I want to sum over 'b' for groups (a = 0, a = 1, a >= 2).
Sample output should be something like,
sum | a
----|---
5 | 0
6 | 1
21 | 2
What query should I be using?
That should do it:
SELECT
CASE
WHEN a = 0 THEN '0'
WHEN a = 1 THEN '1'
WHEN a >= 2 THEN '2'
END AS anotherNameThanA,
SUM(b) AS `sum`
FROM yourTable
GROUP BY anotherNameThanA

SQL with specific LIMIT

I have the next example table:
id | user_id | data
-------------------
1 | 1 | 10
2 | 2 | 10
3 | 2 | 10
4 | 1 | 10
5 | 3 | 10
6 | 4 | 10
7 | 4 | 10
8 | 5 | 10
9 | 5 | 10
10 | 2 | 10
11 | 6 | 10
12 | 3 | 10
13 | 1 | 10
I need to create a SELECT query, that LIMITS my data. For example, I have a limit range (1, 3) (page number = 1, row count = 3). It should selects rows with first 3 unique user_id. And if there are some rows in the end of table with this first user_id's, they should be included to the result. LIMIT statement is bad for this query, because I can get more than 3 rows. Output for my limit should be:
id | user_id | data
-------------------
1 | 1 | 10
2 | 2 | 10
3 | 2 | 10
4 | 1 | 10
5 | 3 | 10
10 | 2 | 10
12 | 3 | 10
13 | 1 | 10
Can you help me to generate this query?
How about:
SELECT *
FROM table
WHERE user_id IN
(SELECT distinct(user_id) FROM table order by user_id LIMIT 3);
What about something like this?
SELECT * FROM table WHERE user_id BETWEEN (number) AND (number+row count)
I know it isn't working but you should be able to make it work ^^
The sample code below can be used for Oracle & Mysql. (use TOP for SQL Server & Sybase)
You get all the results from your table (t1) that match the top 3 user_id (t2) (check the MySQL manual for the limit function)
SELECT *
FROM exampletable t1
INNER JOIN (
SELECT DISTINCT user_id
FROM exampletable
ORDER BY user_id
LIMIT 0,3 -- this is the important part
) AS t2 ON t1.user_id = t2.user_id
ORDER BY id
For the next 3 id's change the limit 0,3 to limit 3,6.