Casting comma separated to integer for IN clause - sqlite

I have three tables estimate, location and department. Now I am JOINing tables location and estimate to get desired results.
Query
SELECT e.id, e.department_ids FROM estimate e JOIN location l ON e.location_id = l.id WHERE e.user_id = '1' and e.delete_flag = 0 and l.active_flag = 1
Result
For above requirement this query was working fine.
Now I want relevant department names as well. So I am using this query
Query
SELECT e.id, e.department_ids, (SELECT group_concat(department, ', ') FROM department WHERE id IN (e.department_ids)) as departmentName FROM estimate e JOIN location l ON e.location_id = l.id WHERE e.user_id = '1' and e.delete_flag = 0 and l.active_flag = 1
Result
which gives me only departments with single department id.
Although if I hardcode e.department as "2, 5" I am getting desired result
Query
SELECT e.id, e.department_ids, (SELECT group_concat(department, ', ') FROM department WHERE id IN (2, 5)) as departmentName FROM estimate e JOIN location l ON e.location_id = l.id WHERE e.user_id = '1' and e.delete_flag = 0 and l.active_flag = 1
Result
I tried cast(e.department_ids as integer), but this is also taking single department_id per row. Is there any function I can cast whole string of e.departments (i.e. "4, 2") so that I can pass that in IN clause?
I got solution for the same in oracle, I could find it's equivalent for sqlite.

I got the desired result using GROUP BY clause.

Related

SQLite - Create dummy variable vector/string from multiple columns

I have some data that looks like this:
UserID Category
------ --------
1 a
1 b
2 c
3 b
3 a
3 c
A I'd like to binary-encode this grouped by UserID: three different values exist in Category, so a binary encoding would be something like:
UserID encoding
------ --------
1 "1, 1, 0"
2 "0, 0, 1"
3 "1, 1, 1"
i.e., all three values are present for UserID = 3, so the corresponding vector is "1, 1, 1".
Is there a way to do this without doing a bunch of CASE WHEN statements? There may be dozens of possible values in Category
Cross join the distinct users to distinct categories and left join to the table.
Then use GROUP_CONCAT() window function which supports an ORDER BY clause, to collect the 0s and 1s:
WITH
users AS (SELECT DISTINCT UserID FROM tablename),
categories AS (
SELECT DISTINCT Category, DENSE_RANK() OVER (ORDER BY Category) rn
FROM tablename
),
cte AS (
SELECT u.UserID, c.rn,
'"' || GROUP_CONCAT(t.UserID IS NOT NULL)
OVER (PARTITION BY u.UserID ORDER BY c.rn) || '"' encoding
FROM users u CROSS JOIN categories c
LEFT JOIN tablename t
ON t.UserID = u.UserID AND t.Category = c.Category
)
SELECT DISTINCT userID,
FIRST_VALUE(encoding) OVER (PARTITION BY UserID ORDER BY rn DESC) encoding
FROM cte
ORDER BY userID
This will work for any number of categories.
See the demo.
Results:
UserID
encoding
1
"1,1,0"
2
"0,0,1"
3
"1,1,1"
First create an encoding table to explicit establish order of categories in the bitmap:
create table e (Category int, Encoding int);
insert into e values ('a', 1), ('b', 2), ('c', 4);
First generate a list of users u (cross) joined with the encoding table e to get a fully populated (UserId, Category, Encoding) table. Then left join the fully populated table with the user supplied data t. The right hand side t can now be used to drive if we need to set a bit or not:
select
u.UserId,
'"' ||
group_concat(case when t.UserId is null then 0 else 1 end, ', ')
|| '"' 'encoding'
from
(select distinct UserID from t) u
join e
left natural join t
group by 1
order by e.Encoding
and it gives the expected result:
1|"1, 1, 0"
2|"0, 0, 1"
3|"1, 1, 1"

I need only one unique result in Oracle sdo_nn Update sentence ,

I need Only one unique result from tableB.Field to tableA.Field
I am using sdo operator sdo_nn, this is the code:
UPDATE table1 t1
SET t1.fieldA = (SELECT T2.fieldB,SDO_NN_DISTANCE(1) distance
FROM table1 T1, table2 T2
WHERE
(sdo_nn(t1.geometry,t2.geometry,'SDO_NUM_RES=1',1)= 'TRUE')
ORDER BY DIST
)
WHERE EXISTS(
SELECT 1
FROM table2 t2
WHERE sdo_nn(t1.geometry, t2.geometry,'SDO_NUM_RES=1',1)='TRUE'
AND(t2.cell_name = 'string1' or t2.cell_name = string2')AND t1.fieldA = NULL
);
In the select sentence of the subquery i get an error because i only use one field(t1.fieldA), but in the sentence i use the operator SDO_NN_DISTANCE(1) and the sql developer count this operator like another field. What is the correct way to write this sentence? I only use sql because i need to insert this code in vba
Thanks!!!
Obviously, you can't (simplified)
set t1.fieldA = (t2.fieldB, distance) --> you want to put two values into a single column
Therefore, get fieldB alone from the subquery which uses analytic function (row_number) to "sort" rows by sdo_nn_distance(1) desc; then get the first row's fieldB value.
Something like this (I hope I set the parenthesis right):
UPDATE table1 t1
SET t1.fieldA =
(SELECT x.fieldB --> only fieldB
FROM (SELECT T2.fieldB, --> from your subquery
SDO_NN_DISTANCE (1) distance,
ROW_NUMBER ()
OVER (ORDER BY sdo_nn_distance (1) DESC) rn
FROM table1 T1, table2 T2
WHERE (sdo_nn (t1.geometry,
t2.geometry,
'SDO_NUM_RES=1',
1) = 'TRUE')) x
WHERE rn = 1) --> where RN = 1
WHERE EXISTS
(SELECT 1
FROM table2 t2
WHERE sdo_nn (t1.geometry,
t2.geometry,
'SDO_NUM_RES=1',
1) = 'TRUE'
AND ( t2.cell_name = 'string1'
OR t2.cell_name = 'string2')
AND t1.fieldA IS NULL);

Recursing through a SQLite table to find a matching subset of records

I have a table with 3 text fields column (A, B & C) imported from a flat file comprising many thousands of lines. None of these fields have a UNIQUE constraint and there is no primary key combination. As a result one or more records may have the same values and there will even be records with the same values across all fields. In many records, columns A, B and C should be the same but due to data quality issues, column C has many variant where column A and B are the same. Where column A and B are the same the corresponding value in column C may be subsets of the value of column C in another record having the same values as other records for column A and B.
To illustrate a subset arrived at by using GROUP BY gives:
enter image description here
I now need to narrow down that subset further to find all records where the value in column C is INSTR the values of the other grouped results i.e. i'd like to return:
enter image description here
because "Buckingham" and "Lindsey" are both INSTR the records that contain "Lindsey Buckingham" in column C
With EXISTS and INSTR():
select t.* from tablename t
where exists (
select 1 from tablename
where a = t.a and b = t.b and c <> t.c and instr(c, t.c) > 0
)
or with LIKE:
select t.* from tablename t
where exists (
select 1 from tablename
where a = t.a and b = t.b and c <> t.c and c like '%' || t.c || '%'
)
or with a self join:
select distinct t.*
from tablename t inner join tablename tt
on tt.a = t.a and tt.b = t.b and tt.c <> t.c and tt.c like '%' || t.c || '%'

SQL query to update value in table to sum of attribute in another table, where the ID's match

I have tried several different queries and cannot seem to find one that works without causing an error
Incorrect syntax near keyword ' '
I have one table called Scores that saves the userID, week number, and that weeks score from a quiz.
Schema:
Scores (Id, userName, weekNumber, currentScore)
There are 12 weeks total, so in the end each user will have 12 entries in this table
I have another table Leaderboard that has schema :
Leaderboard (Id, userName, week1, week2, week3 ..... week12, totalScore)
Each user will only have one entry in this table.
I have been trying to save the sum of the currentScore from Scores into the totalScore attribute of Leaderboard and cannot seem to figure out the correct syntax.
My query is as follows:
UPDATE t1
SET t1.totalScore = t2.completeScore
FROM dbo.Leaderboard AS t1,
((SELECT Id, SUM(weeklyScore) AS completeScore FROM dbo.Scores) as F
INNER JOIN
(SELECT Id FROM dbo.Scores GROUP BY Id) AS S ON F.Id = S.Id) AS t2
WHERE t1.Id = t2.Id
Try this and let us know how it goes:
var total1 = ("UPDATE t1 " +
"SET t1.totalScore = t2.completeScore " +
"FROM dbo.Leaderboard AS t1, (SELECT F.Id, F.completeScore FROM " +
"(SELECT Id, SUM(weeklyScore) AS completeScore FROM dbo.Scores GROUP BY ID) as F " +
"INNER JOIN (SELECT Id FROM dbo.Scores/* GROUP BY Id*/) AS S "+
"ON F.Id = S.Id) AS t2 "+
"WHERE t1.Id = t2.Id");
By the way I think you were missing a GROUP BY clause in the definition of the F derived table and that you don't need the GROUP BY in the definition of the S derived table.

Simple Split function in SQL Server 2012 with explanation pls

I have two tables Procedures and ProcedureTypes.
Procedures has a column Type which is a varchar with the values (1, 2), (3, 4), (4, 5) etc...
ProcedureType has a primary key 'ID' 1 to 9.
ID Description
1 Drug
2 Other-Drug
etc...
ID is an integer value and Type is varchar value.
Now I need to join these two tables to show the values
ID in the Procedures table
ProcedureType in the Procedures table
Description in the ProceduresType table with the value separated by a "-".
For example if he value in Type is (1,2) the new table after join should show values in the description like (Drug-Other Drug)
I have used this query bot to no avail
SELECT * FROM dbo.[Split]((select RequestType from GPsProcedures), ',')
Can anyone tell me how to do it and why the above query is not working
with Procedures as (
select 1 as ID, '1,2,3' as Typ
),
ProcedureTypes as (
select 1 as TypeID, 'Drug' as Name
union select 2 , 'Other-Drug'
union select 3 , 'Test 3'
)
/*Get one extra column of type xml*/
,Procedures_xml as (
select id,CONVERT(xml,' <root> <s>' + REPLACE(Typ,',','</s> <s>') + '</s> </root> ') as Typ_xml
from Procedures
)
/*Convert the field string to multiple rows then join to procedure types*/
, Procdure_With_Type as (
select ID,T.c.value('.','varchar(20)') as TypeID,
ProcedureTypes.Name
from Procedures_xml
CROSS APPLY Typ_xml.nodes('/root/s') T(c)
INNER JOIN ProcedureTypes ON T.c.value('.','varchar(20)') = ProcedureTypes.TypeID
)
/*Finally, group the procedures type names by procedure id*/
select id,
STUFF((
SELECT ', ' + [Name]
FROM Procdure_With_Type inn
WHERE (Procdure_With_Type.ID = inn.ID)
FOR XML PATH(''),TYPE).value('(./text())[1]','VARCHAR(MAX)')
,1,2,'') AS NameValues
from Procdure_With_Type
group by ID
You can't have a select statement as a parameter for a function, so instead of this:
SELECT * FROM dbo.[Split]((select RequestType from GPsProcedures), ',')
Use this:
select S.*
from GPsProcedures P
cross apply dbo.[Split](P.RequestType, ',') S

Resources