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.)
Related
I have a table with 3 columns :
ID
productId
customerId
1
5
1
2
4
1
3
5
1
4
4
1
I want to add a new column called ID_MOD and its value by default will be ID%X (X is a number).
Expected result for X=3 :
ID
productId
customerId
ID_MOD
1
5
1
1
2
4
1
2
3
5
1
0
4
4
1
1
I have X instances of my app and I want each instance to query specific ID_MOD values(0/1/2.../X-1).
Is it possible to use default values for columns? If it is, can the default value be calculated based on other columns ?
what you can do is create a stored function that receives x as an input parameter, and extends your table with a calculated column (at query time).
For example:
.create-or-alter function FunctionName(x:int)
{
TableName
| extend ID_MOD = ID % x
}
If you decide x always has the same value and shouldn't be parameter, you can name the function using the same name as the table, and it will 'hide' the original table.
If the logic of calculating the extended column is well-defined in advance, you can invoke it at ingestion time, using an update policy
I am learning SQLite and I am currently posing the question whether there is a simple way of adding a sequential numbering to the output of a query. Underneath, I provide an example of what I am trying to achieve.
For instance, I have the following query:
SELECT
splTicker AS 'Ticker',
count(splTicker) AS '# of Splits'
FROM Splits
GROUP BY splTicker
ORDER BY count(splTicker) DESC, splTicker ASC;
The output of this query is as follows:
bash-3.2$ sqlite3 myShares < Queries/Split.sql
Ticker # of Splits
---------- -----------
AI.PA 7
ASML.AS 3
BN.PA 3
ALTR.LS 2
BOKA.AS 2
DG.PA 2
...
SON.LS 1
SU.PA 1
SW.PA 1
TEC.PA 1
UMI.BR 1
VIV.PA 1
VPK.AS 1
I am trying to add a sequential number to the rows to obtain the following output:
# Ticker # of Splits
-- ---------- -----------
1 AI.PA 7
2 ASML.AS 3
3 BN.PA 3
4 ALTR.LS 2
5 BOKA.AS 2
6 DG.PA 2
...
Currently, I use a workaround and add the row numbers post-query in Perl. I am posing the question whether I could do this directly in SQLite. The idea seems simple, but I have not found a solution yet. Any help would be appreciated.
Best regards,
GAM
Try this:
SELECT
(SELECT COUNT(*)
FROM Splits AS s2
WHERE s2.splTicker <= s1.splTicker) AS '#',
splTicker AS 'Ticker',
count(splTicker) AS '# of Splits'
FROM Splits s1
GROUP BY s1.splTicker
ORDER BY count(s1.splTicker) DESC, s1.splTicker ASC;
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
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
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.