mysql select minimum that is not a duplicate - sql

I'm trying to write a query that will display the minimum value (lowest score) for each hole eliminating any duplicates. In other words, if the minimum score is 3 on hole_num 1 and there are two or more scores with 3, none of the rows corresponding to hole_num 1 should be returned. However, if there is only one value of 3 on hole_num 1 and it is the minimum value, the row should be returned. Here is what I was able to come up with... unfortunately I can't figure out how to remove the duplicates.
sample table:
player_id hole_num score
------------- ------------ -----
1 1 4
1 2 5
2 1 3
2 2 5
my query that gets the minimum score for each hole_num (but does not eliminate the row if it occurs more than once):
select. r.player_id, r.hole_num, r.score
from scorecard_test r
join (select hole_num,
min(score) best
from scorecard_test
group by hole_num) v on r.hole_num = v.hole_num
and r.score = v.best
produces the following output:
player_id hole_num score
---------- --------- -----
1 2 5
2 1 3
2 2 5
I'm trying to write a query that would only display the second row above (score=3) since 5 on hole_num 2 (although it is minimum) is a repeat. Any help would be greatly appreciated.

A MySQL specific solution is to add a GROUP BY and HAVING COUNT(*) = 1 to your current query:
SELECT r.player_id, r.hole_num, r.score
FROM scorecard_test r
JOIN
(
SELECT hole_num, MIN(score) best
FROM scorecard_test
GROUP BY hole_num
) v
ON r.hole_num = v.hole_num AND r.score = v.best
GROUP BY hole_num, score
HAVING COUNT(*) = 1
A solution that would work more generally is to add one more join to find the unique rows:
SELECT r1.player_id, r1.hole_num, r1.score
FROM scorecard_test r1
JOIN
(
SELECT hole_num, MIN(score) best
FROM scorecard_test
GROUP BY hole_num
) v
ON r1.hole_num = v.hole_num AND r1.score = v.best
LEFT JOIN scorecard_test r2
ON r1.hole_num = r2.hole_num AND r1.player_id != r2.player_id AND r1.score = r2.score
WHERE r2.player_id IS NULL
The result in both cases is this:
player_id hole_num score
---------- --------- -----
2 1 3

You might be looking for this: http://www.w3schools.com/sql/sql_distinct.asp
Doing SELECT DISTINCT ... should return a single row for all that are complete duplicates.

Related

Return all rows where all rows of a child table match all rows of lookup

I need to compare trainers, who have a number of qualifications, against courses, which have a number of
This feels like it should be easy but I just can't get my head round it. Simplified example:
[TrainerQuals]
TrainerID QID
----------------
1 1
2 2
3 1
3 2
[CourseRequiredQuals]
CourseID QID
----------------
1 1
2 2
3 1
3 2
For a given course ID, list trainers allowed to teach that course,
by making sure the trainer has every QID for the course
So, expected output for #courseid = 1
TrainerID
---------
1
3
Expected output for #courseid = 2
TrainerID
---------
2
3
Expected output for #courseid = 3
TrainerID
---------
3
I have tried various join types and conditions but they all give me results where any of the IDs match and no further differences to filter on.
EDIT: Added an SQL Fiddle:
http://sqlfiddle.com/#!18/c852e1/2
A join with aggregation can be used here:
SELECT tq.TrainerID
FROM TrainerQuals tq
LEFT JOIN CourseRequiredQuals crq
ON crq.QID = tq.QID
WHERE crq.CourseID = 1 -- or 2, or 3
GROUP BY tq.TrainerID
HAVING COUNT(*) = COUNT(crq.QID);
The assertion in the HAVING clause ensures that every trainer record has a matching course record.

Find whether id matches and substitute using Case Hive query

I have a table called "Scan" customer transactions where an individual_id appears once for every different transaction and contains column like scan_id.
I have another table called ids which contains random individual_ids sampled from Scan Table
I would like to join ids with scan and get a single record of ids and scan_id if it matches certain values.
Suppose data is like below
Scan table
Ids scan_id
---- ------
1 100
1 111
1 1000
2 100
2 111
3 124
4 1000
4 111
Ids table
id
1
2
3
4
5
I want below output i.e if scan_id matches either 100 or 1000
Id MT
------ ------
1 1
2 1
3 0
4 1
I executed below query and got error
select MT, d.individual_id
from
(
select
CASE
when scan_id in (90069421,53971306,90068594,136739913,195308160) then 1
ELSE 0
END as MT
from scan cs join ids r
on cs.individual_id = r.individual_id
where
base_div_nbr =1
and
country_code ='US'
and
retail_channel_code=1
and visit_date between '2019-01-01' and '2019-12-31'
) as d
group by individual_id;
I would appreciate any suggestions or help with regard to this Hive query. If there is an efficient way of getting this job done. Let me know.
Use a group by:
select s.individual_id,
max(case when s.scan_id in (100, 1000) then 1 else 0 end) as mt
from scan s
group by s.individual_id;
The ids table doesn't seem to be needed for this query.

Oracle SQL - display values up to current record

Can I use LISTAGG or a similar analytical function in Oracle SQL to display all values in group up to current record?
This is my table:
id group_id value
-- -------- -----
1 1 A
2 1 B
3 1 C
4 2 X
5 2 Y
6 2 Z
I would like the following result:
id group_id values
-- -------- ------
1 1 A
2 1 AB
3 1 ABC
4 2 X
5 2 XY
6 2 XYZ
Here is one option, using a correlated subquery to handle the rollup of the value column:
SELECT
t1.id,
t1.group_id,
(SELECT LISTAGG(t2.val, '') WITHIN GROUP (ORDER BY t2.id)
FROM yourTable t2
WHERE t1.group_id = t2.group_id AND t2.id <= t1.id) AS vals
FROM yourTable t1
ORDER BY
t1.id;
Demo
The logic here is that, for each group, with rollup a concatenation of all values coming at or before the current id value in a given row.
Another approach to this, one which might perform and scale better, would be to use a recursive CTE. But, that would take more code, and might be harder to digest than what I wrote above.

SQL Server GROUP BY COUNT Consecutive Rows Only

I have a table called DATA on Microsoft SQL Server 2008 R2 with three non-nullable integer fields: ID, Sequence, and Value. Sequence values with the same ID will be consecutive, but can start with any value. I need a query that will return a count of consecutive rows with the same ID and Value.
For example, let's say I have the following data:
ID Sequence Value
-- -------- -----
1 1 1
5 1 100
5 2 200
5 3 200
5 4 100
10 10 10
I want the following result:
ID Start Value Count
-- ----- ----- -----
1 1 1 1
5 1 100 1
5 2 200 2
5 4 100 1
10 10 10 1
I tried
SELECT ID, MIN([Sequence]) AS Start, Value, COUNT(*) AS [Count]
FROM DATA
GROUP BY ID, Value
ORDER BY ID, Start
but that gives
ID Start Value Count
-- ----- ----- -----
1 1 1 1
5 1 100 2
5 2 200 2
10 10 10 1
which groups all rows with the same values, not just consecutive rows.
Any ideas? From what I've seen, I believe I have to left join the table with itself on consecutive rows using ROW_NUMBER(), but I am not sure exactly how to get counts from that.
Thanks in advance.
You can use Sequence - ROW_NUMBER() OVER (ORDER BY ID, Val, Sequence) AS g to create a group:
SELECT
ID,
MIN(Sequence) AS Sequence,
Val,
COUNT(*) AS cnt
FROM
(
SELECT
ID,
Sequence,
Sequence - ROW_NUMBER() OVER (ORDER BY ID, Val, Sequence) AS g,
Val
FROM
yourtable
) AS s
GROUP BY
ID, Val, g
Please see a fiddle here.

SQL MAX(column) With Additional Criteria

I have a single table, where I want to return a list of the MAX(id) GROUPed by another identifier. However I have a third column that, when it meets a certain criteria, "trumps" rows that don't meet that criteria.
Probably easier to explain with an example. Sample table has:
UniqueId (int)
GroupId (int)
IsPriority (bit)
Raw data:
UniqueId GroupId IsPriority
-----------------------------------
1 1 F
2 1 F
3 1 F
4 1 F
5 1 F
6 2 T
7 2 T
8 2 F
9 2 F
10 2 F
So, because no row in groupId 1 has IsPriority set, we return the highest UniqueId (5). Since groupId 2 has rows with IsPriority set, we return the highest UniqueId with that value (7).
So output would be:
5
7
I can think of ways to brute force this, but I am looking to see if I can do this in a single query.
SQL Fiddle Demo
WITH T
AS (SELECT *,
ROW_NUMBER() OVER (PARTITION BY GroupId
ORDER BY IsPriority DESC, UniqueId DESC ) AS RN
FROM YourTable)
SELECT UniqueId,
GroupId,
IsPriority
FROM T
WHERE RN = 1