combining IDs under GROUP BY? - sqlite

I have an sqlite table "log" that looks like this:
ID p_id viewer
----------------------
1 1 100
2 1 200
3 1 300
4 3 550
5 3 230
6 5 420
7 2 320
8 2 203
9 9 10
10 9 55
And I want to get the average viewers from each p_id. That'd be
SELECT avg(viewer) FROM log GROUP BY p_id
But I want to treat p_id 1 and 5 as the same, so I'd get the average viewers of p_id 1 and 5 combined. How do I do that? Note that the table is much larger, and I need to treat two p_id's as the same multiple times. Can I still do a "group by" to achieve this, or are there other ways?

I tried this and it works with mySQL at least.
SELECT avg(viewer) FROM log GROUP BY CASE p_id WHEN 5 THEN 1 ELSE p_id END;
Edit: When using an alias-table named 'aliases' with the fields 'alias_from_id' and 'aliased_as':
SELECT
CASE ISNULL((SELECT aliased_as FROM aliases WHERE (alias_from_id = log.pid)))
WHEN 1 THEN log.pid ELSE aliased_as END AS the_id,
SUM(value) AS value_sum
FROM log
LEFT JOIN aliases ON (alias_from_id = pid)
GROUP BY
CASE ISNULL((SELECT aliased_as FROM aliases WHERE (alias_from_id = log.pid)))
WHEN 1 THEN log.pid ELSE aliased_as END
I've tested this with mySQL and it works like a charm. It might be possible to simplify this SQL-query a bit but this is the best I can do at the moment :)
Edit2: Changed ISNULL to the corresponding SQLite IFNULL function
SELECT
IFNULL((SELECT aliased_as FROM aliases WHERE (alias_from_id = log.pid)), log.pid) AS the_id,
SUM(value) AS value_sum
FROM log
LEFT JOIN aliases ON (alias_from_id = pid)
GROUP BY
IFNULL((SELECT aliased_as FROM aliases WHERE (alias_from_id = log.pid)), log.pid)
I don't know if SQLite supports the AS keyword, if it doesn't then just remove that keyword - the functionality should be the same.

Related

SQLite - Join returning duplicate result

I've read through dozens of posts on this so apologies if it's easily answered but I'm just not getting it.
Table Name: users
user_id group_id house_name
==========================================
923828395 1 Alpha
722161580 2 Beta
923828395 1 Gamma
Users can be in multiple Groups, and in a different House per Group.
Table Name: points
user_id group_id points term_id
=====================================================================================
722161580 1 18 02078e51
923828395 1 11 02078e51
923828395 2 140 81450fc1
Users can accumulate points in each Group they reside in. In the data above, user_id 923828395 exists in both group_id 1 and 2, accumulating points in both.
Query:
SELECT users.user_id, users.house_name, points.points, points.group_id, points.term_id
FROM users
JOIN points ON points.user_id = users.user_id
WHERE points.term_id = "02078e51" AND points.group_id = "1"
I'm trying to get this to just return 2 rows. However it's returning:
users.user_id users.house_name points.points points.group_id points.term_id
722161580 Beta 18 1 02078e51
923828395 Alpha 11 1 02078e51
923828395 Gamma 11 1 02078e51
I think this is because I've got something wrong with my WHERE .. I've tried flipping that to just an AND statement but I get the same results.
You should join the tables on group_id also:
SELECT u.user_id, u.house_name, p.points, p.group_id, p.term_id
FROM users u JOIN points p
ON p.user_id = u.user_id AND p.group_id = u.group_id
WHERE p.term_id = '02078e51' AND p.group_id = '1'
See the demo.

SQLite: Number rows of query output

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;

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.

Resources