Sqlite: Select last row group by 2 column - sql

I'm trying to get the last row of my table but with 2 column.
+----+-----+---------+
| id1| id2 | info |
+----+-----+---------+
| 1 | 2 | info |
| 2 | 1 | NULL |
| 2 | 3 | info |
| 2 | 1 | NULL |
+----+-----+---------+
I tried:
SELECT * FROM table GROUP BY id1
but I got:
1 2
2 3
2 1
What I need:
2 3
2 1
In other words, I need the last row of each couple ids
Any idea?

SELECT DISTINCT id1, id2 FROM table WHERE id1=2
This should do the trick. Unless you want to apply an aggregation function to other columns, SELECT DISTINCT should to the trick. It will drop any duplicate rows.

If you want to get all items with the highest value dynamically, you can use:
SELECT DISTINCT id1, id2 FROM table WHERE id1=(SELECT MAX(id1))

Related

H2 SQL Sequence count with duplicate values

I have a table of IDs, with some duplicates and I need to create a sequence based on the IDs. I'm trying to achieve the following.
[ROW] [ID] [SEQID]
1 11 1
2 11 2
3 12 1
4 13 1
5 13 2
I'm using an old version of the H2 DB which doesn't have use of windows functions so I have todo this using straight SQL. I have tried joining the table on itself but I'm not getting the result I want as the duplicate values cause issues, any ideas? I have unique identifier in row number, but not sure how to use this to achieve what I want?
SELECT A.ID, COUNT(*) FROM TABLE A
JOIN TABLE B
ON A.ID = B.ID
WHERE A.ID >= B.ID
GROUP BY A.ID;
Use a subquery that counts the seqid:
select
t.row, t.id,
(select count(*) from tablename where id = t.id and row <= t.row) seqid
from tablename t
It's not as efficient as window functions but it does what you expect.
See the demo (for MySql but it's standard SQL).
Results:
| row | id | seqid |
| --- | --- | ----- |
| 1 | 11 | 1 |
| 2 | 11 | 2 |
| 3 | 12 | 1 |
| 4 | 13 | 1 |
| 5 | 13 | 2 |

select column1 from table A based on unique value of another column2 in table B

I have table A and table B and need to select a column1 from table A based on unique value of another column in table B
table A
id | product |
1 | A |
1 | B |
1 | A |
2 | A |
3 | B |
4 | A |
table B
id | product | date
1 | A | 1/01/2017
1 | B | 1/02/2017
1 | A | 1/01/2017
2 | A | 1/01/2017
3 | B | 1/02/2017
4 | A | 1/01/2017
I want the output to be : 2,3,4
i.e. all the 'id's' which have a unique value in 'date' column of table B
Depending upon the actual restrictions in your tables, there are a couple of options.
Option 1 - assuming that for example ID=1, Product=A, date=1/01/2017 and ID=1, Product=B, date=1/01/2017 means that ID=1 IS NOT included in your final result as it has 2 entries for the date = 1/01/2017 even though they are for different Products
SELECT a.ID
FROM
(
SELECT ID, COUNT(*)
FROM TableB
GROUP BY ID
HAVING COUNT(*) = 1
) a
Option 2 - assuming that for example ID=1, Product=A, date=1/01/2017 and ID=1, Product=B, date=1/01/2017 means that ID=1 IS included in your final result as it only has a single date for each ID/Product combination
SELECT DISTINCT ID
FROM
(
SELECT ID, Product, COUNT(*)
FROM TableB
GROUP BY ID, Product
HAVING COUNT(*) = 1
) a

Count the occurrences of duplicate values among columns of a table

I've a table where each column contains integers and some values are duplicates.
Here the example:
| ColumnA | Column B | Column C |
| 2 | 3 | 1 |
| 1 | 1 | 3 |
| 2 | 1 | 3 |
How can I do a SQL query in order to count the occurrences of each integer?
I want to obtain something like that:
the count for 2 is 2, the count for 1 is 4, the count for 3 is 3
try this:
SELECT Col, COUNT(*) AS TOT
FROM (
SELECT ColumnA AS Col FROM table
UNION ALL
SELECT ColumnB FROM table
UNION ALL
SELECT ColumnC FROM table
) AS A
GROUP BY Col

How to pivot a table in oracle SQL that has no feature to use as columns?

I have a query that looks like this
select
parentid,
id
from
table
order by
parentid;
The parentid is a reference to another type of object in a different table. The records in this table are additional information about the record in the parent table, and there can be anywhere from 1 to 10 ids associated with a parent id. The records don't have any particular order, either. So right now, the query above returns something like this:
parentid | id
---------------------------
1 10
1 20
1 30
1 40
2 50
2 60
3 70
4 80
4 90
4 100
I'd like to transform the results into a table like this
parentid | id1 | id2 | id3 | id4 ....
--------------------------------------------------------------------
1 10 20 30 40
2 50 60
3 70
4 80 90 100
I don't really care what column the ids end up in, since there's no order, but I do want each of them to be assigned to some column associated with the parent id. I thought about using pivot, but the examples I have seen make it look like you have to have an ordering or some other unique identifier associated with the ids to transform them into columns. There's no such field that could order or otherwise distinguish these records from one another. Is there a way to pivot without this, or to randomly assign some attribute that I could then use to pivot on?
Also, not sure if it will matter to the answer, but the table above is also a trivialization of the actual data for the sake of clarity - in reality there's tens of thousands of parent ids and records in this table.
Just create your column:
SqlFiddleDemo
SELECT 'ID' || ROW_NUMBER() OVER (PARTITION BY "parentid" ORDER BY "id") AS rn,
"parentid",
"id"
FROM Table1
OUTPUT
| RN | parentid | id |
|-----|----------|-----|
| ID1 | 1 | 10 |
| ID2 | 1 | 20 |
| ID3 | 1 | 30 |
| ID4 | 1 | 40 |
| ID1 | 2 | 50 |
| ID2 | 2 | 60 |
| ID1 | 3 | 70 |
| ID1 | 4 | 80 |
| ID2 | 4 | 90 |
| ID3 | 4 | 100 |
Or use this version if have more than 9 columns
SELECT 'ID' || LPAD(rn, 2, '0') as rn,
"parentid",
"id"
FROM (
SELECT ROW_NUMBER() OVER (PARTITION BY "parentid" ORDER BY "id") AS rn,
"parentid",
"id"
FROM Table1
) T

SQL distinct/groupby on combination of columns

I am trying to do a SQL select on a table based on two columns, but not in the usual way where the combination of values in both columns must be unique; I want to select where the value can only appear once in either column.
Given the dataset:
|pkid | fkself | otherData |
|-----+--------+-----------|
| 1 | 4 | there |
| 4 | 1 | will |
| 3 | 6 | be |
| 2 | 5 | other |
| 5 | 2 | data |
| 6 | 3 | columns |
I need to return either
|pkid | fkself | otherData |
|-----+--------+-----------|
| 1 | 4 | there |
| 3 | 6 | be |
| 2 | 5 | other |
or
|pkid | fkself | otherData |
|-----+--------+-----------|
| 4 | 1 | will |
| 5 | 2 | data |
| 6 | 3 | columns |
The only way I can think of to do this is to concatenate `pkid and fkid in order so that both row 1 and row 2 would concatenate to 1,4, but I'm not sure how to do that, or if it is even possible.
The rows will have other data columns, but it does not matter which row I get, only that I get each ID only once, whether the value is in pkid or fkself.
You can use least and greatest to get the smallest or biggest value of the two. That allows you to put them in the right order to generate those keys for you. You could concatenate the values as you suggested, but it's not needed in this solution. With dense_rank you can generate a sequence for each of those fictional keys. Then, you can get the first OtherData from that sequence.
select
pkid,
fkself,
otherData
from
(select
pkid,
fkself,
otherData,
dense_rank() over (partition by least(pkid, fkself), greatest(pkid, fkself) order by pkid) as rank
from
YourTable t)
where
rank = 1
Your idea is possible, and it should produce the results you want.
SELECT DISTINCT joinedID
FROM (
SELECT min(id) & "," & max(id) as joinedID
FROM (
SELECT pkid as id, someUniqueValue
FROM table
UNION ALL
SELECT fkself as id, someUniqueValue
FROM table)
GROUP BY someUniqueValue )
This will give you a unique list of IDs, concatenated as you like. You can easily include other fields by adding them to each SELECT statement. Also, someUniqueValue can be either an existing unique field, a new unique field, or the concatenated pkid and fkself, if that combination is unique.
The only way I can think of to do this is to concatenate `pkid and
fkid in order so that both row 1 and row 2 would concatenate to 1,4,
but I'm not sure how to do that, or if it is even possible.
You could do it using a CASE statement in Oracle:
SQL> SELECT * FROM sample
2 /
PKID FKSELF
---------- ----------
1 4
4 1
3 6
2 5
5 2
7 7
6 rows selected.
SQL> l
1 SELECT DISTINCT *
2 FROM (
3 SELECT CASE WHEN pkid <= fkself THEN pkid||','||fkself
4 ELSE fkself||','||pkid
5 END "JOINED"
6 FROM sample
7* )
SQL> /
JOINED
-------------------------------------------------------------------------------
1,4
2,5
3,6
7,7