How to query based on priority of column values - sql

I have a table
| group | col1 | col2 |
| 1 | test1 | val1 |
| 1 | test2 | val2 |
| 3 | test3 | val3 |
| 3 | test4 | val4 |
I need to select rows by priority. For example, if row has col1 value as test1 so show it. If it's not then show test2. Don't remember about group. Just if values in one group.
I expect this result:
| group | col1 | col2 |
| 1 | test1 | val1 |
| 3 | test3 | val3 |

In standard SQL, you seem to want:
select t.*
from t
order by (case when col1 = 'test1' then 1
when col2 = 'test2' then 2
else 3
end)
fetch first 1 row only;
EDIT:
For the revised question, you can use distinct on:
select distinct on (group) t.*
from t
order by group,
(col1 = 'test1') desc,
(col1 = 'test2') desc;

Please use below query,
select * from
(select group, col1, col2, row_number() over (partition by group order by col1) as rnk
from table) where rnk = 1;

This is the query that work!
select * from
(select group,
col1,
col2,
row_number() over (partition by group order by (case when col1 = 'test1' then 2
when col1 = 'test2' then 1
else 3
end)) as rnk
from test) AS tab1 where rnk = 1;

Related

Get rows with maximum count per one column - while grouping by two columns

I'm trying to get max count of a field.
This is what I get and what I'm tried to do.
| col1 | col2 |
| A | B |
| A | B |
| A | D |
| A | D |
| A | D |
| C | F |
| C | G |
| C | F |
I'm trying to get the max count occurrences of col2, grouped by col1.
With this query I get the occurrences grouped by col1 and col2.
SELECT col1, col2, count(*) as conta
FROM tab
WHERE
GROUP by col1, col2
ORDER BY col1, col2
And I get:
| col1 | col2 | conta |
| A | B | 2 |
| A | D | 3 |
| C | F | 2 |
| C | G | 1 |
Then I used this query to get max of count:
SELECT max(conta) as conta2, col1
FROM (
SELECT col1, col2, count(*) as conta
FROM tab
WHERE
GROUP BY col1, col2
ORDER BY col1, col2
) AS derivedTable
GROUP BY col1
And I get:
| col1 | conta |
| A | 3 |
| C | 2 |
What I'm missing is the value of col2. I would like something like this:
| col1 | col2 | conta |
| A | D | 3 |
| C | F | 2 |
The problem is that if I try to select the col2 field, I get an error message, that I have to use this field in group by or aggregation function, but using it in the group by it's not the right way.
Simpler & faster (and correct):
SELECT DISTINCT ON (col1)
col1, col2, count(*) AS conta
FROM tab
GROUP BY col1, col2
ORDER BY col1, conta DESC;
db<>fiddle here (based on a_horse's fiddle)
DISTINCT ON is applied after aggregation, so we don't need a subquery or CTE. Consider the sequence of events in a SELECT query:
Best way to get result count before LIMIT was applied
Select first row in each GROUP BY group?
You can combine GROUP BY with a window function - which gets evaluated after the group by:
with cte as (
SELECT col1, col2,
count(*) as conta,
dense_rank() over (partition by col1 order by count(*) desc) as rnk
FROM tab
WHERE ...
GROUP by col1, col2
)
select col1, col2, conta
from cte
where rnk = 1
order by col1, col2;
This will return the combination of col1,col2 with the same highest max count twice. If you don't want that, use row_number() instead of dense_rank()
Online example
Possibly not the most elegant solution, but using a common table expression may help.
with cte as (
select col1, col2, count(*) as total
from dtable
group by col1, col2
)
select col1, col2, total
from cte c
where total = (select max(total)
from cte cc
where cc.col1 = c.col1)
order by col1 asc
Returns
col1|col2|total|
----+----+-----+
A | D | 3|
C | F | 2|
from the docs
I misunderstood the question. Here is your solution:
;with tablex as
(Select col1, col2, Count(col2) as Count From Your_Table Group by col1, col2),
aaaa as
(Select ROW_NUMBER() over (partition by col1 order by Count desc) as row, * From tablex)
Select * From aaaa Where row = 1
Using a window function:
select distinct on (col1) col1, col2, cnt
from
(
select col1, col2, count(*) over (partition by col1, col2) cnt
from the_table
) t
order by col1, cnt desc;
col1
col2
cnt
A
D
3
C
F
2
This solution does not solve cases with ties.

If 2 rows have the same ID select one with the greater other column value

I'm having difficulty getting my head round this one, which should be simple.
When selecting from the table, if multiple rows have the same ID then select the row which has a greater value in Col2.
Here is my sample table:
ID | Col2 |
----------------
123 | 1 |
123 | 2 |
1234 | 2 |
12345 | 3 |
Expected output:
ID | Col2 |
----------------
123 | 2 |
1234 | 2 |
12345 | 3 |
For this example, group by is sufficient;
select id, max(col2) as col2
from t
group by id;
If you want the row with the maximum column, then I would often recommend row_number():
select t.*
from (select t.*, row_number() over (partition by id order by col2 desc) as seqnum
from t
) t
where seqnum = 1;
However, the "old-fashioned" method might have better performance:
select t.*
from t
where t.col2 = (select max(t2.col2) from t t2 where t2.id = t.id);
NOT EXISTS operator can also be used:
SELECT * FROM Table1 t1
WHERE NOT EXISTS(
SELECT 'Anything' FROM Table1 t2
WHERE t1.id = t2.id
AND t1.Col2 < t2.col2
)
Demo: http://sqlfiddle.com/#!18/5e1d6/3
| ID | Col2 |
|-------|------|
| 123 | 2 |
| 1234 | 2 |
| 12345 | 3 |

Trying to write a query that will display duplicates results as null

I have a table that looks like the first example.
I'm trying to write a MSSQL2012 statement that that will display results like the second example.
Basically I want null values instead of duplicate values in columns 1 and 2. This is for readability purposes during reporting.
This seems like it should be possible, but I'm drawing a blank. No amount of joins or unions I've written has rendered the results I need.
| Col1 | Col2 | Col3 |
+------+------+------+
| 1 | 2 | 4 |
| 1 | 2 | 5 |
| 1 | 3 | 6 |
| 1 | 3 | 7 |
+------+------+------+
| Col1 | Col2 | Col3 |
+------+------+------+
| 1 | 2 | 4 |
| Null | null | 5 |
| null | 3 | 6 |
| null | null | 7 |
+------+------+------+
I would do this with no subqueries at all:
select (case when row_number() over (partition by col1 order by col2, col3) = 1
then col1
end) as col1,
(case when row_number() over (partition by col2 order by col3) = 1
then col2
end) as col2,
col3
from t
order by t.col1, t.col2, t.col3;
Note that the order by at the end of the query is very important. The result set that you want depends critically on the ordering of the rows. Without the order by, the result set could be in any order. So, the query might look like it works, and then suddenly fail one day or on a slightly different set of data.
Using a common table expression with row_number():
;with cte as (
select *
, rn_1 = row_number() over (partition by col1 order by col2, col3)
, rn_2 = row_number() over (partition by col1, col2 order by col3)
from t
)
select
col1 = case when rn_1 > 1 then null else col1 end
, col2 = case when rn_2 > 1 then null else col2 end
, col3
from cte
without the cte
select
col1 = case when rn_1 > 1 then null else col1 end
, col2 = case when rn_2 > 1 then null else col2 end
, col3
from (
select *
, rn_1 = row_number() over (partition by col1 order by col2, col3)
, rn_2 = row_number() over (partition by col1, col2 order by col3)
from t
) sub
rextester demo: http://rextester.com/UYA17142
returns:
+------+------+------+
| col1 | col2 | col3 |
+------+------+------+
| 1 | 2 | 4 |
| NULL | NULL | 5 |
| NULL | 3 | 6 |
| NULL | NULL | 7 |
+------+------+------+

Select duplicate rows

I have data like this :
| col1 |
--------
| 1 |
| 2 |
| 1 |
| 2 |
| 1 |
| 2 |
| 1 |
| 2 |
| 1 |
| 2 |
How can I get like this and order by MAX to Min :
| col1 |
--------
| 2 |
| 1 |
I try this :
SELECT col1 , count(col1 ) FROM myTable GROUP BY col1
But I got strange results
If you want to order by the count of occurences of each value:
SELECT col1, count(1) FROM myTable GROUP BY col1 ORDER BY count(1) DESC
If you want to order by the actual value contained in col1
SELECT DISTINCT col1 FROM myTable ORDER BY col1 DESC
You can use the SQL DISTINCT keyword to only show unique results.
SELECT DISTINCT col1 FROM myTable;
You can then order by that column.
SELECT DISTINCT col1 FROM myTable ORDER BY col1 DESC;

SQL select distinct rows

I have data like this (col2 is of type Date)
| col1 | col2 |
------------------------------
| 1 | 17/10/2007 07:19:07 |
| 1 | 17/10/2007 07:18:56 |
| 1 | 31/12/2070 |
| 2 | 28/11/2008 15:23:14 |
| 2 | 31/12/2070 |
How would select rows which col1 is distinct and the value of col2 is the greatest. Like this
| col1 | col2 |
------------------------------
| 1 | 31/12/2070 |
| 2 | 31/12/2070 |
SELECT col1, MAX(col2) FROM some_table GROUP BY col1;
select col1, max(col2)
from table
group by col1
i reckon it would be
select col1, max(col2)
from DemoTable
group by col1
unless i've missed something obvious
select col1, max(col2) from MyTable
group by col1
SELECT Col1, MAX(Col2) FROM YourTable GROUP BY Col1
In Oracle and MS SQL:
SELECT *
FROM (
SELECT t.*, ROW_NUMBER() OVER (PARTITION BY col1 ORDER BY col2 DESC) rn
FROM table t
) q
WHERE rn = 1
This will select other columns along with col1 and col2