Sqlite query - How I can select a predecessor? - sql

I have this table below:
ID name Last
0 Joe Doe
1 Hut Nob
2 Lis Hug
3 Edy mur
I use this query to select an ID:
SELECT name FROM myDatabase WHERE ID = 2
In this case the query returns me the string Lis, now, How I can select the predecessor value?
Simple, the predecessor from 2 is 1, so I need only to do WHERE ID < 2 or WHERE ID = 2 - 1.
But this method have a problem! Lets suppose that I delete that row (ID = 1), the query will return null, because that ID not exists.
So, in this example, how I can select the predecessor from ID 2 and return ID 0? (ID 1 is gone)

You can use subquery to find max ID that is lower than ID that you provided:
SELECT *
FROM mytable m
WHERE m.id = (SELECT MAX(m2.id)
FROM mytable m2
WHERE m2.ID < 2);
SqlFiddleDemo

Get all the smaller IDs, and from those, take only the largest one:
SELECT name
FROM MyTable
WHERE ID < 2
ORDER BY ID DESC
LIMIT 1;

Related

SQL - group by occurrence and return id

I have a table of IDs and value:
ID Value
X 1
X 1
X 2
Y 5
Y 5
Y 5
Z 3
Z 6
I want to see which ID contains more than 1 different value. In this case return ID X and Y because X contains[1,2] and Z contains [3,6]:
ID
X
Z
I have tried this:
select ID from
(
SELECT ID
,count(*) over (partition by [Value]) as c
FROM mytable
) a
where c>1
But this is not returning the desired answer
I prefer aggregating this way:
SELECT ID
FROM mytable
GROUP BY ID
HAVING MIN(Value) <> MAX(Value);
On many databases, the above HAVING clause will be sargable, meaning that an index on (ID, Value) can be used. The version which checks COUNT(DISTINCT Value) may not be able to use such an index.
Try this,
SELECT ID
FROM mytable
GROUP BY ID
HAVING COUNT(DISTINCT Value) > 1;
Just group them by ID and check wheter it got more than 1 occurrencies in Value field. Something like this
SELECT ID
FROM table
GROUP BY ID
HAVING COUNT(DISTINCT Value) > 1
CREATE TABLE yourtable(
ID VARCHAR(30) NOT NULL
,Value int NOT NULL
);
INSERT INTO yourtable
(ID,Value) VALUES
('X',1),
('X',1),
('X',2),
('Y',5),
('Y',5),
('Y',5),
('Z',3),
('Z',6);
Other approaches are far better,but I used Rank and Subquery to distinguish ID with more than one occurrence.
SELECT ID
FROM   (SELECT *,
               Rank()
                 OVER(
                   partition BY ID
                   ORDER BY Value) ID2
        FROM   yourtable) a
WHERE ID2 > 1
dbfiddle

SQL for Exclude

I have a table which is a simple lists of ID numbers and NAMES - I am trying to write a SQL which only returns rows where the NAME does not have particular IDs.
This has been stumping me - the query below returns all as they have other IDs from the exclude lists (large range of IDs). How to structure a query where only those who don't have ID 2 or 3 are returned -- i.e. only returns 'bob' for table below.
select * from TABLE where ID not in (2, 3)
ID NAMES
1 bob
1 alice
2 alice
1 dave
2 dave
3 dave
4 dave
Thank you.
One method is group by and having:
select name
from t
group by name
having sum(case when ID in (2, 3) then 1 else 0 end) = 0;
If you want the original ids, you can add listagg(id, ',') within group (order by id) to the select. Or use not exists:
select t.*
from t
where not exists (select 1
from t t2
where t2.name = t.name and
t2.id in (2, 3)
);

Select rows base on Subset

I've a scenario where I need to write sql query base on result of other query.
Consider the table data:
id attribute
1 a
1 b
2 a
3 a
3 b
3 c
I want to write query to select id base on attribute set.
I mean first I need to check attribute of id 1 using this query:
select attribute from table where id = 1
then base on this result I need to select subset of attribute. like in our case 1(a,b) is the subset of 3(a,b,c). My query should return 3 on that case.
And if I want to check base on 2(a) which is the subset of 1(a,b) and 3(a,b,c), it should return 1 and 3.
I hope, it's understandable. :)
You could use this query.
Logic is simple: If there isn't any item in A and isn't in B --> A is subset of B.
DECLARE #SampleData AS TABLE
(
Id int, attribute varchar(5)
)
INSERT INTO #SampleData
VALUES (1,'a'), (1,'b'),
(2,'a'),
(3,'a'),(3,'b'),(3,'c')
DECLARE #FilterId int = 1
;WITH temp AS
(
SELECT DISTINCT sd.Id FROM #SampleData sd
)
SELECT * FROM temp t
WHERE t.Id <> #FilterId
AND NOT EXISTS (
SELECT sd2.attribute FROM #SampleData sd2
WHERE sd2.Id = #FilterId
AND NOT EXISTS (SELECT * FROM #SampleData sd WHERE sd.Id = t.Id AND sd.attribute = sd2.attribute)
)
Demo link: Rextester
I would compose a query for that in three steps: first I'd get the attributes of the desired id, and this is the query you wrote
select attribute from table where id = 1
Then I would get the number of attributes for the required id
select count(distinct attribute) from table where id = 1
Finally I would use the above results as filters
select id
from table
where id <> 1 and
attribute in (
select attribute from table where id = 1 /* Step 1 */
)
group by id
having count(distinct attribute) = (
select count(distinct attribute) from table where id = 1 /* Step 2 */
)
This will get you all the id's that have a number of attributes among those of the initially provided id equal to the number the initial id has.

db2 query which shows records repeated for each value in another table

I need to insert records into e.g. table 1 by creating a new instance of each existing record in the table for every record in one of the reference tables e.g. ref table 1.
So, for example...
Table 1
ID = 1, Name = John, Ref Table 1 ID = null
Ref Table 1
ID = 1, Name = Grade 1
ID = 2, Name = Grade 2
Wanted result from SQL
Table 1
ID = 1, Name = John, Ref Table 1 ID = 1
ID = 2, Name = John, Ref Table 1 ID = 2
or even
ID = 1, Name = John, Ref Table 1 ID = null
ID = 2, Name = John, Ref Table 1 ID = 1
ID = 3, Name = John, Ref Table 1 ID = 2
Is this possible using standard SQL?
Looking to get it all in one query as at the moment it looks like I'll have to repeat it for each ref table 1 record.
Thanks
Maybe I'm missing something, but why not just do:
SELECT * FROM tbl_1, tbl_2
Result would be:
tbl_1.ID tbl_1.Name Ref Table ID tbl_2.ID tbl_2.Name
1 John 1 Grade 1
1 John 2 Grade 2
Where tbl_1
ID Name Ref Table ID
1 John NULL
and tbl_2
ID Name
1 Grade 1
2 Grade 2
At last, just select the required columns.
Try something like this:
Create table for insert results:
CREATE TABLE to_insert(
ID INTEGER NOT NULL GENERATED ALWAYS AS IDENTITY (START WITH 1 INCREMENT BY 1)
,Name VARCHAR(100)
,Ref_Table1_ID INTEGER
,PRIMARY KEY(ID)
,FOREIGN KEY(Ref_Table1_ID) REFERENCES(ref_table_1)
);
Execute insert query:
INSERT INTO to_insert(Name, Ref_Table1_ID)
SELECT t1.Name, COALESCE(t1.Ref_Table1_ID, rt1.ID) Ref_Table1_ID
FROM table_1 t1 FULL OUTER JOIN ref_table_1 rt1 ON (t1.Ref_Table1_ID = rt1.ID)

How to GROUP multiple records from two different SQL statements

I have a table called tbl which contains all the data I need. I have many columns in this table, but for purposes of this example I will only list the columns necessary to accomplish this task.
Here's how data stored in the tbl (note uID is char(20) and cID is int)*:
uID cID
1 10
1 11
1 12
2 11
We usually query this table like
SELECT * FROM tbl WHERE uID = "1"
So it returns
uID cID
1 10
1 11
1 12
But I also need to return the row where uID is different but cID do match. Or grab the uID of the second row (which is 2) based on cID and do a select statement like this:
SELECT * FROM tbl WHERE uID in ('1','2')
That query will return what I'm looking for
uID cID
1 10
1 11
1 12
2 11
This table contains a lot of rows and I want to be able to do this programatically for every call where cID matches and uID is different.
Any suggestions?
I think this may be what you want:
SELECT *
FROM tbl
WHERE uID = '1'
UNION ALL
SELECT *
FROM tbl
WHERE uID <> '1' AND
EXISTS (select 1 from tbl tbl2 where tbl2.uId = '1' and tbl2.cID = tbl.cID);
or something like this:
SELECT uID, cID
FROM tbl
WHERE uID IN
(
SELECT uID
FROM tbl
INNER JOIN
(
SELECT cID
FROM tbl
GROUP BY cID
HAVING count(*) > 1
) c ON c.cID = tbl.cID
)