Get all ids of GROUP_CONCAT in SQLite - sqlite

Table B
id name tablename
1 abc table1
2 xyz table2
3 abc table1
4 sdf table2
5 dfg table1
Query:
SELECT B.tablename, GROUP_CONCAT(B.id),GROUP_CONCAT(B.name||'-'||cnt)
FROM (
SELECT tablename, id, name, COUNT(*) cnt
FROM B
GROUP BY tablename,name
) B GROUP BY B.tablename
Output:
| tablename | GROUP_CONCAT(B.id) | GROUP_CONCAT(B.nameB||'-'||cnt) |
| ------ | ------------------ | ------------------------------- |
| table1 | 1,5 | abc-2,dfg-1 |
| table2 | 2,4 | xyz-1,sdf-1 |
But here i'm not getting full ids as you can see in output of table 1.
i want something like :
| tablename | GROUP_CONCAT(B.id) | GROUP_CONCAT(B.nameB||'-'||cnt) |
| ------ | ------------------ | ------------------------------- |
| table1 | 1,3,5 | abc-2,df-1 |
| table2 | 2,4 | xyz-1,sdf-1 |
Pls help me fix this.

You should use GROUP_CONCAT() for the ids in the subquery also:
SELECT tablename, GROUP_CONCAT(id), GROUP_CONCAT(name||'-'||cnt)
FROM (
SELECT tablename, GROUP_CONCAT(id) id, name, COUNT(*) cnt
FROM B
GROUP BY tablename, name
)
GROUP BY tablename
See the demo.

Related

Sqlite / populate new column that ranks the existing rows

I've a SQLite database table with the following columns:
| day | place | visitors |
-------------------------------------
| 2021-05-01 | AAA | 20 |
| 2021-05-01 | BBB | 10 |
| 2021-05-01 | CCC | 3 |
| 2021-05-02 | AAA | 5 |
| 2021-05-02 | BBB | 7 |
| 2021-05-02 | CCC | 2 |
Now I would like to introduce a column 'rank' which indicates the rank according to the visitors each day. Expected table would look like:
| day | place | visitors | Rank |
------------------------------------------
| 2021-05-01 | AAA | 20 | 1 |
| 2021-05-01 | BBB | 10 | 2 |
| 2021-05-01 | CCC | 3 | 3 |
| 2021-05-02 | AAA | 5 | 2 |
| 2021-05-02 | BBB | 7 | 1 |
| 2021-05-02 | CCC | 2 | 3 |
Populating the data for the new column Rank can be done with a program like (Pseudocode).
for each i_day in all_days:
SELECT
ROW_NUMBER () OVER (ORDER BY `visitors` DESC) Day_Rank, place
FROM mytable
WHERE `day` = 'i_day'
for each i_place in all_places:
UPDATE mytable
SET rank= Day_Rank
WHERE `Day`='i_day'
AND place = 'i_place'
Since this line by line update is quite inefficient, I'm searching how to optimize this with a SQL sub query in combination with the UPDATE.
(does not work so far...)
for each i_day in all_days:
UPDATE mytable
SET rank= (
SELECT
ROW_NUMBER () OVER (ORDER BY `visitors` DESC) Day_Rank
FROM mytable
WHERE `day` = 'i_day'
)
Typically, this can be done with a subquery that counts the number of rows with visitors greater than the value of visitors of the current row:
UPDATE mytable
SET Day_Rank = (
SELECT COUNT(*) + 1
FROM mytable m
WHERE m.day = mytable.day AND m.visitors > mytable.visitors
);
Note that the result is actually what RANK() would return, if there are ties in the values of visitors.
See the demo.
Or, you could calculate the rankings with ROW_NUMBER() in a CTE and use it in a subquery:
WITH cte AS (
SELECT *, ROW_NUMBER() OVER (PARTITION BY day ORDER BY visitors DESC) rn
FROM mytable
)
UPDATE mytable
SET Day_Rank = (SELECT rn FROM cte c WHERE (c.day, c.place) = (mytable.day, mytable.place));
See the demo.
Or, if your versipn of SQLite is 3.33.0+ you can use the join-like UPDATE...FROM... syntax:
UPDATE mytable AS m
SET Day_Rank = t.rn
FROM (
SELECT *, ROW_NUMBER() OVER (PARTITION BY day ORDER BY visitors DESC) rn
FROM mytable
) t
WHERE (t.day, t.place) = (m.day, m.place);

sql count of rows from two tables where rows from table 1 don't exist in table 2

I have two tables in a SQLite db like so
| t1 |
|===============|
| t1_id | other |
|-------|-------|
| 1 | sdfds |
| 2 | asdaa |
| 3 | lkjeq |
| t2 |
|=======================|
| t2_id | t1_id | other |
|-------|-------|-------|
| 1 | 1 | dggeh |
| 2 | 1 | iohio |
| 3 | 3 | ytucc |
| 4 | 3 | .noih |
| 5 | 3 | /oioi |
There are approx. 300K+ rows in both tables. I want the counts of t1 that have related rows in t2 as well as those that don't have. That is,
"count of t1 with related t2" : 2
"count of t1 with no related t2": 1
Of course, I can get "count of t1 with related t2" from
SELECT Count(*) FROM t1 JOIN t2 ON t1.t1_id = t2.t1_id;
and the "count of t1 with no related t2" by subtracting the above from the total count of t1. But how can I get it from a SQL query efficiently? I tried the following
EXPLAIN QUERY PLAN SELECT t1_id FROM t1 AS t
WHERE NOT EXISTS (SELECT * FROM t2 WHERE t.t1_id = t2.t1_id);
and I see that the index on t1_id in table t2 is not used. When I try the query, it takes really long, like 100s of seconds.
A couple of possibilities:
SELECT count(*) FROM
(SELECT t1_id FROM t1
EXCEPT
SELECT t1_id FROM t2);
or
SELECT count(*)
FROM t1
WHERE t1_id NOT IN (SELECT t1_id FROM t2);
or (A slight variation on your original):
SELECT count(*)
FROM t1
WHERE NOT EXISTS (SELECT 1 FROM t2 WHERE t1.t1_id = t2.t1_id);
All three of those should use an index on t2(t1_idx). You'll have to do benchmarking on real data to see which is faster.

SQLite - Update a column based on values from two other tables' columns

I am trying to update Data1's ID to Record2's ID when:
Record1's and Record2's Name are the same, and
Weight is greater in Record2.
Record1
| ID | Weight | Name |
|----|--------|------|
| 1 | 10 | a |
| 2 | 10 | b |
| 3 | 10 | c |
Record2
| ID | Weight | Name |
|----|--------|------|
| 4 | 20 | a |
| 5 | 20 | b |
| 6 | 20 | c |
Data1
| ID | Weight |
|----|--------|
| 4 | 40 |
| 5 | 40 |
I have tried the following SQLite query:
update data1
set id =
(select record2.id
from record2,record1
where record1.name=record2.name
and record1.weight<record2.weight)
where id in
(select record1.id
from record1, record2
where record1.name=record2.name
and record1.weight<record2.weight)
Using the above query Data1's id is updated to 4 for all records.
NOTE: Record1's ID is the foreign key for Data1.
For the given data set the following seems to serve the cause:
update data1
set id =
(select record2.id
from record2,record1
where
data1.id = record1.id
and record1.name=record2.name
and record1.weight<record2.weight)
where id in
(select record1.id
from record1, record2
where
record1.id in (select id from data1)
and record1.name=record2.name
and record1.weight<record2.weight)
;
See it in action: SQL Fiddle.
Please comment if and as this requires adjustment / further detail.

SQLITE get row continous value

I have a simple table. One of the example rows looks like this:
id | name |
1 | a |
2 | a |
3 | a |
4 | b |
6 | b |
7 | a |
8 | a |
I want to get last continuous id.
so if i start at '1', the result should be '4'
in this example, the result should be '7'
3 |a |
4 |b |
5 |a |
6 |a |
7 |a |
10|a |
Only i now is that select all after my input number, and find continuous programmatically.
how can i do..?
If I understand the question correctly, this should work for you:
select id from tableName t1 where not exists(select id from tableName t2 where t2.id=t1.id+1) and (id-(select count(*) from tableName t3 where t3.id<t1.id))=(select min(id) from tableName);
If you want to start from 10, it should be:
select id from tableName t1 where not exists(select id from tableName t2 where t2.id=t1.id+1) and (id-(select count(*) from tableName t3 where t3.id<t1.id and t3.id>=10))=10;

how to sum the column and get the rows based on month and year

It is my table can i get result for this .
Each user have points,i have to show number of user points got in current month,current year
Thanks.
--------------------------------
| userId | points | date |
--------------------------------
| 1 | 5 | 8/25/2013 |
| 1 | 3 | 8/16/2013 |
| 1 | 2 | 8/01/2013 |
| 1 | 2 | 9/25/2013 |
| 1 | 5 | 8/25/2013 |
| 1 | 3 | 2/16/2012 |
| 2 | NULL | NULL |
| 2 | NULL | NULL |
--------------------------------
They result should be like :
---------------------------------------------------
| userId | CurrentMonthpoints | CurrentYearPoints |
---------------------------------------------------
| 1 | 15 | 17 |
| 2 | NULL | NULL |
---------------------------------------------------
My request :
SELECT userId,
(SELECT sum(points)
from tbl_points
WHERE PointsDate between '8/1/2013' and '8/31/2013') AS CurrentMonthPoints,
(SELECT distinct SUM(points)
from tbl_points
WHERE PointsDate between '1/1/2014' and '12/31/2014' ) AS CurrentYearPoints
from tbl_user_performance_points
But My query shows wrongly as :
---------------------------------------------------
| userId | CurrentMonthpoints | CurrentYearPoints |
---------------------------------------------------
| 1 | 15 | 17 |
| 2 | 15 | 17 |
---------------------------------------------------
Advance Thanks
Give this a try:
select a.userID,
a.points_sum_m as currentmonthpoints,
b.points_sum_y as currentyearpoints
from (select userID, sum(points) as points_sum_m
from tbl_points
where month(date) = month(getdate())
group by userID) a
inner join (select userID, sum(points) as points_sum_y
from tbl_points
where year(date) = year(getdate())
group by userID) b
on a.userID = b.userID;
SQLFiddle: http://sqlfiddle.com/#!3/ff780/12
with month_cte(userid,Current_Month) as
(select userid,sum(Points)Current_Month from tbl_points
where datepart(mm,PointsDate)=datepart(mm,getdate()) and datepart(YY,PointsDate)=datepart(yy,getdate()) group by userid)
, year_cte(userid,Current_year) as
(select userid,sum(Points)Current_Year from tbl_points
where datepart(YY,PointsDate)=datepart(yy,getdate()) group by userid)
select Distinct t.Userid, Current_Month, Current_Year From tbl_points T
left join month_cte mc on T.userid=mc.userid
left join year_cte yc on t.userid=yc.userid
if you just want to correct your query replace it with this...
SELECT userId,
(SELECT sum(points)
from tbl_points
WHERE PointsDate between '8/1/2013' and '8/31/2013' and userId= X.UserId) AS CurrentMonthPoints,
(SELECT distinct SUM(points)
from tbl_points
WHERE PointsDate between '1/1/2014' and '12/31/2014' and userId = X.UserId) AS CurrentYearPoints
from tbl_user_performance_points X

Resources