SQL : select distinct of one column while ignoring other columns - mysql

So I have a table like this :
---------
id, keyid
---------
1, 3
1, 5
1, 6
2, 1
2, 1
2, 3
4, 1
I want the output of the query to be
1,3
2,1
4,1
If i use select distinct(id,keyid) from table it applies the distinct on the pair of id,keyid and not just id alone.

select id, min(keyid) from tbl group by id

If you want the min value of KeyId for each Id, then user194076's answer will definitely work.
If you want the first occurring value of KeyId for each Id, you could use:
WITH CTE AS (
SELECT Id, KeyId, ROW_NUMBER() OVER (PARTITION BY Id ORDER BY Id) AS RN
FROM tbl
)
SELECT Id, KeyId FROM CTE WHERE RN = 1
I've tested both using STATISTICS IO and STATISTICS TIME and they appear to be the same in terms of performance, so really depends on what your exact needs are.

Related

How to get the MAX value in MySQL?

How to get the MAX value in every albumID(45, 12, 22, 8) in the following table?
I tried with this query.
But it returned me the first value, not max value.(3, 6, 5, 6)
SELECT
*
FROM
(
SELECT
*
FROM
contentnew
WHERE
genreID = 1
ORDER BY
albumID DESC,
reg_count DESC
) AS newTB
GROUP BY
albumID;
Look this
If I use the
Once you group by, you can apply aggregate functions such as max on each group. In your example try:
SELECT albumID, max(reg_count) as max_count
FROM contentnew
GROUP BY albumID
This will project each albumID with the max_count in the group. In the select statement you can only use aggregate functions. The reason why we are able to project (or print) albumID is because this is the column we grouped by.
Following comments:
SELECT *
FROM contentnew as c1
WHERE c1.reg_count < (
SELECT max(c2.reg_count)
FROM contentnew as c2
WHERE c1.albumID = c2.albumID
GROUP BY c2.albumID)
You can try
select max(reg_count) from contentnew group by albumID
You are almost there, one thing that might be helpful is to use row_number() function, if you want every column from the table.
with contentnew_test
as
(
select row_number() over (partition by albumId order by reg_count desc) row
,* from
contentnew
)
select * from contentnew_test where row = 1 order by reg_count desc;
I used this as a reference as not sure about the syntax
https://www.mysqltutorial.org/mysql-window-functions/mysql-row_number-function/
Subquery will give you a result set something like this:
row albumId reg_count ...
1 1 8 ...
2 1 7 ...
3 1 3 ...
4 1 1 ...
1 2 22 ...
2 2 9 ...
3 2 6 ...
4 2 1...and so on.

How to create multiple rows from a initial row

I use mysql db engine, I wonder is it possible that the data in the table one row transferred to another table, this table would consist of two columns, id and value
each of the transferred value would go into one row and row would look like ID, value, and for as long as it has a value that is transferred to new row maintains the id as long as it has a value that belonged to the id of a row from which it transferred
Initial table looks like
id |country_name |city_1 |city_2 |city_3 |city_4
------------------------------------------------------------------------
1 |Some_country |some_city1 |some_city2 |some_city3 |some_city4
Wanted table looks like
id | city_name
1 | some_city1
1 | some_city2
1 | some_city3
1 | some_city4
Use this for one particular ID
select id, city_name from(
select id, city_1 as city_name from yourTable
union all
select id, city_2 from yourTable
union all
select id, city_3 from yourTable
union all
select id, city_4 from yourTable
) as t where id= yourID
http://sqlfiddle.com/#!9/7ee1f/1
Use this for whole table
select id, city_name from(
select id, city_1 as city_name from yourTable
union all
select id, city_2 from yourTable
union all
select id, city_3 from yourTable
union all
select id, city_4 from yourTable
) as t
order by id
What you are looking for is often referred to as vertical pivoting: you want to pivot something like an array of four city names - hard-wired into the table definition - into four vertical rows.
The solution is a cross join with a temporary table with as many consecutive integers, starting from 1, as you have columns to pivot, in conjunction with a CASE-WHEN expression that makes use of that series of integers.
See here:
WITH foo(id,country_name,city_1,city_2,city_3,city_4) AS (
SELECT 1,'Some_country','some_city1','some_city2','some_city3','some_city4'
)
, four_indexes(idx) AS (
SELECT 1
UNION ALL SELECT 2
UNION ALL SELECT 3
UNION ALL SELECT 4
)
SELECT
id AS country_id
, idx AS city_id
, CASE idx
WHEN 1 THEN city_1
WHEN 2 THEN city_2
WHEN 3 THEN city_3
WHEN 4 THEN city_4
ELSE ''
END AS city_name
FROM foo CROSS JOIN four_indexes
;
country_id|city_id|city_name
1| 1|some_city1
1| 3|some_city3
1| 2|some_city2
1| 4|some_city4
Only the other day, I answered a question that was looking for reversing the operation we are performing here: horizontal pivoting.
See here if you're curious ...
How to go about a column with different values in a same row in sql?
Happy Playing -
Marco the Sane

SELECT from external data in MySQL

Let's consider a made up example
SELECT id, name, score.score FROM
someTable,
(select someTableId, count(*) as score FROM SecondTable GROUP BY someTableId) as score
WHERE score.someTableId == id
ORDER BY score.score DESC
Let's now assume that I have a backend computing my scoring, and that I would like to remove the subquery and insert my own data instead. I would like to know how to do this.
I would like to do something like (this is the question, because what's below doesn't work):
SELECT id, name, score.score FROM
someTable,
((12,324), (1, 342)) as score(id, score)
WHERE score.someTableId == id
ORDER BY score.score DESC
Here is an example of external data substitution to a subquery:
SELECT * FROM users WHERE id IN (SELECT user_id FROM posts WHERE thread_id = 12 GROUP BY user_id);
Without a subquery and with external data:
SELECT * FROM users WHERE id IN (1,2,3);
If I understood you correctly :
SELECT id, name, score.score FROM
someTable,
(SELECT 12 as someTableId,324 as score UNION ALL SELECT 1, 342 <UNION ALL....>) as score(id, score)
WHERE score.someTableId == id
ORDER BY score.score DESC
Thats the only way you can do it, it doesn't actually replace the the subquery, but it replace the select from the table and can improve performance if thats what you are looking for.
In MySQL you don't need to specify a from clause like a dummy table when you are just looking to fetch dummy data.
Other DBMS require a dummy table name (typically DUAL) but in MySQL it's rather straightforward:
SELECT 12 AS id, 324 AS score
UNION ALL SELECT 2, 65
UNION ALL SELECT 3, 598
UNION ALL SELECT 4, 244
You can use this as any other result-set.

how to make rows into column using pivot

i have an date like this
Name VALUE
ClientID M01010001250
InterviewType 1
InterviewDate 7/8/2011
ClientID M01010001260
InterviewType 1
InterviewDate 7/8/2011
ClientID M01010001260
InterviewType 5
InterviewDate 1869-07-01
ClientID M01010001290
InterviewType 1
InterviewDate 7/8/2011
now my out put should be like this
SEQ ClientID InterviewType InterviewDate
1 M01100016550 5 9/9/2011
2 M01100016550 5 9/9/2011
3 M01030000680 5 9/9/2011
i have written a query using pivot :
SELECT SEQ,ClientID,InterviewType,InterviewDate
FROM
(SELECT ROW_NUMBER() OVER (PARTITION BY NAME,VALUE ORDER BY NAME,VALUE) AS SEQ,NAME,VALUE
FROM Table1) DT
PIVOT (MAX(VALUE)FOR NAME IN(ClientID,InterviewType,InterviewDate))DT1
ORDER BY SEQ
even though i am using row_number it is not giving desired output suggest me
Your issue here is to group all the rows in three. I have a working solutions :
;WITH MyCTE AS
(
SELECT ROW_NUMBER() OVER (ORDER BY orderby) AS SEQ,
NAME,
VALUE
FROM (
select 1 as orderby,
*
from Table1
)t
)
SELECT SEQ,
ClientID,
InterviewType,
InterviewDate
FROM (
SELECT ((SEQ-1)/3)+1 AS SEQ,
NAME,
VALUE
FROM MyCTE
) DT
PIVOT (
MAX(VALUE)
FOR NAME
IN(ClientID,InterviewType,InterviewDate)
)DT1
ORDER BY SEQ
You may find an SQL Fiddle Demo
Your query isn't working because it's numbering the rows based on their value, so regardless of the order they go in, the rows with the lowest values will be first. Your row which has InterviewType 5 will always have the highest rownumber if the other rows all have InterviewType =1.
Without a way to uniquely identify which entries are supposed to go together, the order returned from queries in SQL server isn't guaranteed. However, if your data is in that exact format mentioned above - so the rows are always in the format ClientId, then InterviewType then InterviewDate, the following should work.
select p.*
from (select *,
CEILING((ROW_NUMBER() OVER (ORDER BY (SELECT 1)) - 1) / 3) as [Row]
from Table1 t) t
PIVOT (max(value) for name in (ClientID, InterviewType, InterviewDate)) p
Output on my test data:
0 M01050001250 16 7/8/2011
1 M01010001260 1 7/8/2011
2 M01010001260 5 1869-07-01
3 M01010001290 1 7/8/2011
(The ceiling function is numbering every three rows - first three are 0, then the next three are 1, etc.)

ROW_NUMBER() alternative

I have a table which contains:
ID ID_TYPE
---------------
1 0
2 1
3 1
Now I want to get the current record number when performing:
SELECT ID
FROM IDTable
WHERE ID_TYPE = 1
I don't want to use ROW_NUMBER() OVER (ORDER BY [ID] desc), because it's very slow when using larger tables.
What are my alternatives ?
Try
select ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) as number from IDTable WHERE ID_TYPE = 1