SQLite: Query not responding when key = null - sqlite

I have the following tables
R:
rid, wid, sid, attend
1 1 3 1
2 1 2 0
3 2 3 1
4 3 1 0
5 2 1 1
6 4 1 1
E:
eid, wid,sid
1 1 3
2 2 1
W:
wid, title
1 title1
2 title2
3 title3
4 title4
I want to retrieve the title of W where the wid is in R but not in E. Naturally, I will use LEFT OUTER JOIN. I wrote the following query
SELECT DISTINCT w.title
FROM E LEFT OUTER JOIN R
ON R.sid = E.sid AND R.wid = E.wid
JOIN W
ON R.wid = W.wid
WHERE R.sid = 1 AND R.attend = 1
this will return the titles of wid that exists in both tables R and E: title2 and title3. However, I want to retrieve the titles of wid that exists in R but not in E i.e: title4. Therefore, when I LEFT OUTER JOIN R with E, the columns of E that does not have matching values in R will be filled with NULL values -as far as I know-. Though, when I use the clause WHERE E.sid = NULL or ON E.sid = NULL the query does not retrieve anything what so ever. I tried to retrieve from the table with simple query like
SELECT * FROM E where sid = NULL but it would not retrieve anything although I added a row with sid = null just to test.
so, maybe there is a problem with SQLite supporting null values or maybe it is just something in my query.
I have been searching for a week now. I hope I can find some help here as I usually do.

the first link that #AFract provided helped me. I had two problems.
I was putting table E on the left hand side of the LEFT OUTER JOIN and table R on the right, which does not give proper output. I had to switch their positions
apparently the syntax E.sid = NULL does not work for SQLite although it is written in their documentation on the official site. the correct syntax that worked for me is E.sid IS NULL
so I modified my query as following
SELECT DISTINCT W.title
FROM R LEFT OUTER JOIN E
ON R.sid = E.sid AND R.wid = E.wid JOIN W ON R.wid = W.wid
WHERE R.sid = 1 AND E.sid IS NULL AND R.attend = 1

Related

walking list using cte

Still learning SQL :)
This time I'd like to a 'linked list' walk from a table I guess using CTE.
Despite all the example on the web I could not find one simple example I could start from then peek and poke from there.
Here is my table
create table yo (id integer, nx integer)
select * from yo
id nx
---------- ----------
1 5
2 4
3 7
4 9
5 3
6 0
7 0
8 6
9 8
I'd like to get a list of 'id','nx' from yo following the next link 'nx' given a start 'id'
So a start 'id' of 1 would produce
id nx
---------- ----------
1 5
3 7
5 3
7 0
Note that 0 is a end marker.
I can't find the magic SQL for doing this
Thanx in advance
Cheers,
Phi
The first row of the list is easy:
SELECT id, nx
FROM yo
WHERE id = 1
If the nx column of the previous entry is available as list.nx, the next entry can be returned with this query:
SELECT yo.id, yo.nx
FROM yo
JOIN list ON yo.id = list.nx
Then just plug these together:
WITH RECURSIVE list(id, nx) AS (
SELECT id, nx
FROM yo
WHERE id = 1
UNION ALL
SELECT yo.id, yo.nx
FROM yo
JOIN list ON yo.id = list.nx
)
SELECT * FROM list
(This stops automatically because there is no row where id is zero; otherwise, you could add a WHERE list.nx != 0.)

How can I concatenate(or merge) values from 2 result sets with the same PK?

I don't know if I'm being dumb here but I can't seem to find an efficient way to do this. I wrote a very long and inefficient query that does what I need, but what I WANT is a more efficient way.
I have 2 result sets that displays an ID (a PK which is generic/from the same source in both sets) and a FLAG (A - approve and V - Validate).
Result Set 1
ID FLAG
1 V
2 V
3 V
4 V
5 V
6 V
Result Set 2
ID FLAG
2 A
5 A
7 A
8 A
I want to "merge" these two sets to give me this output:
ID FLAG
1 V
2 (V/A)
3 V
4 V
5 (V/A)
6 V
7 A
8 A
Neither of the 2 result sets will at any time have all the ID's to make a simple left join with a case statement on the other result set an easy solution.
I'm currently doing a union between the two sets to get ALL the ID's. Thereafter I left join the 2 result sets to get the required '(V/A)' by use of a case statement.
There must be a more efficient way but I just can't seem to figure it out now as I'm running low on amps... I need a holiday... :-/
Thanks in advance!
Use a FULL OUTER JOIN:
SELECT ID,
CASE
WHEN t1.FLAG IS NULL THEN t2.FLAG
WHEN t2.FLAG IS NULL THEN t1.FLAG
ELSE '(' || t1.FLAG || '/' || t2.FLAG || ')'
END AS MERGED_FLAG
FROM TABLE1 t1
FULL OUTER JOIN TABLE2 t2
USING (ID)
ORDER BY ID
See this SQLFiddle.
Share and enjoy.
I think that you can use xmlagg. Here an exemple :
SELECT deptno,
SUBSTR (REPLACE (REPLACE (XMLAGG (XMLELEMENT ("x", ename)
ORDER BY ename),'</x>'),'<x>','|'),2) as concated_list
FROM emp
GROUP BY deptno
ORDER BY deptno;
Bye

Sqlite Query to search in a combination of several columns concated to on string

I am stuck with a query in an Sqlite Database.
The complete table structure is a bit complex so I will make an example that is broken down to my Problem.
I have 2 tables like
T1
_id name v1 v2 v3
1 test 4 3 1
2 to 1 2 2
3 show 2 2 2
4 what 4 2 4
5 I 1 1 1
6 mean 3 3 1
T2
_id name
1 this
2 is
3 a
4 test
v1, v2, v3 are the foreign keys of T2 _id and in combination will result in one string.
In this example:
T1 _id 1: testathis
T1 _id 2: thisisis
T1 _id 3: isisis
T1 _id 4: testistest
T1 _id 5: thisthisthis
T1 _id 6: aatest
And in this resulting string I want to search and get a result table.
For example if the search string is "isi" (in the sql query "%isi%") I want to get a result table like this:
name v1v2v3
to thisisis
show isisis
It is propably quit easy but I am totally stuck here.
I tried already several ways including group_concat() and various combinations of select ... where clauses.
Although I tried a query similar to this one.
But I am allways failing on the fact that the string has to be concated from rows of another table.
Karl, give this is try:
select t1.name, t21.name || t22.name || t23.name as v1v2v3 from t1
join t2 t21 on t1.v1 = t21._id
join t2 t22 on t1.v2 = t22._id
join t2 t23 on t1.v3 = t23._id
where t21.name || t22.name || t23.name like '%isi%'
I don't have SQLite to test it right now, but it should work :)
SELECT
T1.name as name,
tmpV1.name || tmpV2.name || tmpV3.name as v1v2v3
FROM
T1
JOIN
T2 as tmpV1 on T1.v1 = tmpV1._id
JOIN
T2 as tmpV2 on T1.v2 = tmpV2._id
JOIN
T2 as tmpV3 on T1.v3 = tmpV3._id
WHERE
v1v2v3 like '%isi%'
;
Edit: aww Mosty beat me.

Filtering in Oracle based on a group of values contained in a list of values

I have following two tables:
ID_PERSON NAME
-----------------
1 John
2 Joe
3 Peter
ID_PERSON ID_SPECIALIZATION
------------------------------
1 5
1 6
1 7
2 5
2 1
3 6
3 10
I need to filter data based on group of ids ID_SPECIALIZATION that will be provided. For example
I want to display only those persons who has specialization in 5 and 6 so it will return only first person. In ASP.NET Web form there will be two listboxes, left and right button, in first LB there will be all possible specializations and user will choose some of them to second LB as filtering options. I have no idea how to put this filtering condition in sql query. Thanks for help.
You could use the following:
SQL> SELECT p.id_person, p.NAME
2 FROM person p
3 JOIN person_spe s ON p.id_person = s.id_person
4 WHERE id_specialization IN (5, 6)
5 GROUP BY p.id_person, p.NAME
6 HAVING COUNT(*) = 2;
ID_PERSON NAME
---------- -----
1 John
One way to do it:
SELECT
ID_PERSON
, NAME
FROM
Person AS p
WHERE EXISTS
( SELECT *
FROM
PersonSpecialization AS ps
WHERE ps.ID_PERSON = p.ID_PERSON
AND ps.ID_SPECIALIZATION = 5
)
AND EXISTS
( SELECT *
FROM
PersonSpecialization AS ps
WHERE ps.ID_PERSON = p.ID_PERSON
AND ps.ID_SPECIALIZATION = 6
)
SELECT d1.id_person, d1.name FROM tbl_table1 d1
INNER JOIN tbl_table2 d1
ON d1.ID_PERSON=d2.ID_PERSON
WHERE ID_SPECILIZATION = ?
Theres the query but I'm not sure how asp.net works and passing in the value. It might be work looking up bind variables which allows you to use place holders in the sql which oracle then caches the query and just uses the values that you pass in at run tuime using EXECUTE IMMEDIATE.

Getting an SQL statement to output a table in a certain order

I'm doing a test web shop that has sections within sections. There can be an unlimited number of levels so I have just one table Section.
The table has the following columns:
SectionID, SectionTitle, SectionLevel, ParentID, PageOrder
SectionLevel: 1 being topmost (no parent)
PageOrder: Within it's parent group, which order it should go in.
And for test data :
SectionID SectionTitle SectionLevel ParentID PageOrder
--------- ------------ ------------ -------- ---------
2 Ladies 1 0 2
3 Mens 1 0 3
4 Jewellery 2 2 1
5 Clothing 2 2 2
6 Clothing 2 3 1
7 Accessories 2 3 2
I want to return this data in one table so that the first top level section is first, and then all of it's children's sections are next, and then the second top level section etc.
I've had a play around with it but can't get to come out right. I think that it should be possible to do it if I redesigned the table but can't think how.
The data should come back in the following order:
SectionID SectionTitle SectionLevel ParentID PageOrder
--------- ------------ ------------ -------- ---------
2 Ladies 1 0 2
4 Jewellery 2 2 1
5 Clothing 2 2 2
3 Mens 1 0 3
6 Clothing 2 3 1
7 Accessories 2 3 2
WITH tree (SectionID, ParentID, SectionLevel, SectionTitle) AS
(
SELECT SectionID, ofs.ParentID, ofs.SectionLevel, ofs.SectionTitle
FROM Section ofs
WHERE ofs.ParentID = 0
ORDER BY SectionID
UNION ALL
SELECT SectionID, ofs.ParentID, ofs.SectionLevel, ofs.SectionTitle
FROM Section ofs
JOIN tree ON tree.ID = ofs.ParentID
ORDER BY PageOrder
)
This is deliberately slightly niaive to make it easier on my fingers. It can be tuned if necessary to allow more nodes in the tree to be accomodated.
DECLARE
#maxPageOrder INT,
#maxLevel INT,
#multiplier INT
SELECT
#maxPageOrder = MAX(PageOrder) + 1,
#maxLevel = MAX(SectionLevel)
FROM
Section
SELECT
#multiplier = POWER(#maxPageOrder, #maxLevel - 1)
;
WITH
recursed_tree
AS
(
SELECT
SectionID AS SectionID,
PageOrder * #multiplier AS finalOrder,
#multiplier / #maxPageOrder AS multiplier
FROM
Section
WHERE
ParentID = 0
UNION ALL
SELECT
child.SectionID,
parent.finalOrder + child.PageOrder * parent.multiplier,
parent.multiplier / #maxPageOrder
FROM
recursed_tree AS parent
INNER JOIN
Section AS child
ON child.ParentID = parent.SectionID
)
SELECT
Section.*
FROM
Section
INNER JOIN
recursed_tree
ON Section.SectionID = recursed_tree.SectionID
ORDER BY
recursed_tree.finalOrder
Note: This assumes all page orders start from 1, rather than 0.
Here's the messy solution I was talking about..
select
a.SectionID, a.SectionTitle, a.SectionLevel, a.ParentID, a.PageOrder
from
section a
left outer join section b on b.SectionID=a.ParentID
left outer join section c on c.SectionID=b.ParentID
order by
c.PageOrder, b.PageOrder, a.PageOrder
As I mentioned in the comment, better to do it in code.. this is only for 3 levels (you could make it more by adding another outer join and order by clause).
This is rather complicated in SQL. If you have access to Safari Books, there are some relevant sections in Joe Celko's Trees and Hierarchies in SQL for Smarties.

Resources