**CODE** **TYPE**
--------------------
XXOPT POD
XXOPT FPOD
MSC OPR
KLM OPR
40DV SZTP
90DV SZTP
MMVD POD
KKLP FPOD
SSRG FPOD
I HAVE A DATA TABLE COMING FROM DATA BASE
I WANT TO SHOW MY RESULT LIKE FOLLOWING FORMAT
NOTE: HERE POD,FPOD,OPR,SZTP ARE STATIC TYPES
POD: XXOPT,MMVD
FPOD: XXOPT,KKLP,SSRG
OPR: MSC,KLM
SZTP: 40DV, 90DV
WILL YOU PLESSE HELP ME TO SHOW ABOVE FORMAT AS OUT PUT.
DECLARE #MyTable TABLE(
[CODE] NVARCHAR(50) NOT NULL,
[TYPE] NVARCHAR(50) NOT NULL
);
INSERT #MyTable ([CODE],[TYPE])
SELECT 'XXOPT','POD'
UNION ALL SELECT 'XXOPT','FPOD'
UNION ALL SELECT 'MSC','OPR'
UNION ALL SELECT 'KLM','OPR'
UNION ALL SELECT '40DV','SZTP'
UNION ALL SELECT '90DV','SZTP'
UNION ALL SELECT 'MMVD','POD'
UNION ALL SELECT 'KKLP','FPOD'
UNION ALL SELECT 'SSRG','FPOD';
SELECT x.[TYPE],y.GROUP_CONCAT
FROM (SELECT [TYPE] FROM #MyTable GROUP BY [TYPE]) x
CROSS APPLY(
SELECT STUFF((SELECT ','+y.CODE
FROM #MyTable y
WHERE y.[TYPE]=x.[TYPE]
FOR XML PATH('')),1,1,'') AS GROUP_CONCAT
)y;
Results:
TYPE GROUP_CONCAT
---- ---------------
FPOD XXOPT,KKLP,SSRG
OPR MSC,KLM
POD XXOPT,MMVD
SZTP 40DV,90DV
Note: In this case you need an index on ([TYPE])+INCLUDE([CODE]) or an index on ([TYPE],[CODE]).
Related
In Sqlite, I defined a view as a union all of two tables. When I run queries using that view, the index is used if the query is simple enough. For certain complex queries, it does not and ends up running full table scans. Are there ways around this so that I can use views performantly?
Table/View Definitions:
CREATE TABLE 'Table1' (Id varchar (18) PRIMARY KEY UNIQUE ON CONFLICT ROLLBACK, Name varchar (255) )
CREATE TABLE 'Table2' (Id varchar (18) PRIMARY KEY UNIQUE ON CONFLICT ROLLBACK, Name varchar (255) )
CREATE TABLE 'Table3' (Id varchar (18) PRIMARY KEY UNIQUE ON CONFLICT ROLLBACK, Name varchar (255) )
CREATE VIEW [UnionView] AS SELECT 'T1' tid, T1.rowid, T1.* FROM [Table1] T1 UNION ALL SELECT 'T2' tid, T2.rowid, T2.* FROM [Table2] T2
Simple Query (indexes are used):
SELECT Id FROM [UnionView] WHERE Id = 'asdf'
Explain Query Plan:
COMPOUND QUERY
LEFT-MOST SUBQUERY
SEARCH TABLE Table1 AS T1 USING INDEX sqlite_autoindex_Table1_1 (Id=?)
UNION ALL
SEARCH TABLE Table2 AS T2 USING INDEX sqlite_autoindex_Table2_1 (Id=?)
LEFT JOIN Query (indexes are not used):
SELECT T3.Id FROM [Table3] T3 LEFT JOIN [UnionView] T ON T3.Id=T.Id WHERE T3.Id = 'asdf'
Explain Query Plan
MATERIALIZE 2
COMPOUND QUERY
LEFT-MOST SUBQUERY
SCAN TABLE Table1 AS T1
UNION ALL
SCAN TABLE Table2 AS T2
SEARCH TABLE Table3 AS T3 USING COVERING INDEX sqlite_autoindex_Table3_1 (Id=?)
SCAN SUBQUERY 2 AS T
Your complex query does full table scans of Table1 and Table2 because you are not doing any filtering on UnionView.
It does use though sqlite_autoindex_Table3_1.
Also, the WHERE clause is applied after the joins.
If you filter UnionView before the join then indexes will be used:
EXPLAIN QUERY PLAN
SELECT T3.Id
FROM [Table3] T3
LEFT JOIN (SELECT Id FROM [UnionView] WHERE Id = 'asdf') T
ON T3.Id=T.Id
WHERE T3.Id = 'asdf'
Result:
MATERIALIZE 3
COMPOUND QUERY
LEFT-MOST SUBQUERY
SEARCH TABLE Table1 AS T1 USING INDEX sqlite_autoindex_Table1_1 (Id=?)
UNION ALL
SEARCH TABLE Table2 AS T2 USING INDEX sqlite_autoindex_Table2_1 (Id=?)
SEARCH TABLE Table3 AS T3 USING COVERING INDEX sqlite_autoindex_Table3_1 (Id=?)
SCAN SUBQUERY 3
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
I am running below query in Teradata editor:
SELECT 'EMP_INFO_MAIN' as TABLE_NAME, COUNT(1) as RECORD_COUNT FROM SCHEMA.TABLE1 UNION ALL
SELECT 'EMP_SAL' as TABLE_NAME, COUNT(1) as RECORD_COUNT FROM SCHEMA.TABLE2 UNION ALL
SELECT 'DEPARTMENT_INFO' as TABLE_NAME, COUNT(1) as RECORD_COUNT FROM SCHEMA.TABLE3;
The query is giving me below result:
TABLE_NAME | RECORD_COUNT
------------|-------------
EMP_INFO | 10
EMP_SAL | 11
DEPARTME | 110
The first column is not showing complete table name.
Can anyone please help here?
This is a common issue.
In Teradata the first SELECT of a UNION determines the resulting data typ and the column name, so either change the order of SELECTs to start with the longest name or add a CAST in the 1st SELECT:
SELECT CAST('EMP_INFO_MAIN' AS VARCHAR(20)) as TABLE_NAME, COUNT(1) as RECORD_COUNT FROM SCHEMA.TABLE1 UNION ALL
SELECT 'EMP_SAL' as TABLE_NAME, COUNT(1) as RECORD_COUNT FROM SCHEMA.TABLE2 UNION ALL
SELECT 'DEPARTMENT_INFO' as TABLE_NAME, COUNT(1) as RECORD_COUNT FROM SCHEMA.TABLE3;
I need to delete some rows in a SQLite table with two columns as primary key, like this:
DELETE FROM apt_lang
WHERE (apt_fk, apt_lang_fk) NOT IN ((42122,"en"),(42123,"es"),(42123,"en"))
This works on Oracle and MySQL but not in SQLite.
Can anybody help me?
First, find out which rows you want to delete.
The easiest way is with a join:
SELECT *
FROM apt_lang
JOIN (SELECT 42122 AS apt_fk, 'en' AS apt_lang_fk UNION ALL
SELECT 42123 , 'es' UNION ALL
SELECT 42123 , 'en' )
USING (apt_fk, apt_lang_fk)
To use this with a DELTE, either check with EXISTS for a match:
DELETE FROM apt_lang
WHERE NOT EXISTS (SELECT 1
FROM apt_lang AS a2
JOIN (SELECT 42122 AS apt_fk, 'en' AS apt_lang_fk UNION ALL
SELECT 42123 , 'es' UNION ALL
SELECT 42123 , 'en' )
USING (apt_fk, apt_lang_fk)
WHERE apt_fk = apt_lang.apt_fk
AND apt_lang_fk = apt_lang.apt_lang_fk)
or get the ROWIDs of the subquery and check against those:
DELETE FROM apt_lang
WHERE rowid NOT IN (SELECT apt_lang.rowid
FROM apt_lang
JOIN (SELECT 42122 AS apt_fk, 'en' AS apt_lang_fk UNION ALL
SELECT 42123 , 'es' UNION ALL
SELECT 42123 , 'en' )
USING (apt_fk, apt_lang_fk))
This should work:
DELETE FROM apt_lang WHERE (apt_fk, apt_lang_fk) NOT IN (VALUES (42122,"en"),(42123,"es"),(42123,"en"))
Yes, it's possible to delete rows from SQLite based on a subquery that builds on multiple columns. This can be done with SQLite's concatenate "||" operator. It might help to show an example.
Setup:
create table a (x,y);
insert into a values ('A','B');
insert into a values ('A','C');
create table b (x,y);
insert into b values ('A','C');
insert into b values ('A','X');
Show Tables:
select * from a;
A|B
A|C
select * from b;
A|C
A|X
Assuming you want to delete from table a rows where column x and column y don't match with table b, the following select will accomplish that.
delete from a where x||y not in (select a.x||a.y from a,b where a.x=b.x and a.y=b.y);
Result:
select * from a;
A|B
Summary
This relies on concatenating several columns into one with the "||" operator. Note, it will work on calculated values too, but it might require casting the values. So, just a few conversions to note with the "||" operator...
select 9+12|| 'test';
21 -- Note we lost 'test'
select cast(9+12 as text)|| 'test';
21test -- Good! 'test' is there.
i have one Schedule Table like
i want to look like select query data is:
1 and 11 is Duplicate trainer and Duplicate day,time
10 and 12 is Duplicate trainer, Duplicate vanueid and Duplicate date,time
so last two column are display is not Duplicate than available and is Duplicate than display notavailable
Here is the solution that is coming to my mind.There may some syntax issue but i given the logic which may help you.
DECLARE #duplicate TABLE (
trainerId INT,
dt varchar(50)
)
INSERT INTO #duplicate SELECT TrainerId , [Date] from tbl GROUP BY TrainerId , Date HAVING (COUNT(*) > 1)
SELECT * FROM #duplicate
DECLARE #tempTable TABLE (
trainerId INT,
dt varchar(50),
status int
)
INSERT INTO #tempTable
SELECT trainerId , [Date] , STATUS = (SELECT COUNT(*) FROM #duplicate where trainerId = tbl.TrainerId and dt = tbl.Date) FROM tbl
![enter image description here][2]SELECT * , CASE [status] WHEN 0 THEN 'Available' ELSE 'Not Available' END FROM #tempTable