I have a table value in sqlite like..
i'm getting value in sqlite query like this..
select * from tablename where id='101' and id='102' and id='1' and id='18'
101 Local Local Local Local Local Local
102 9 12 9 12 9
1 3:55 4:20 4:40 5:00 5:20 5:40
18 4:50 5:15 5:35 5:55 6:15 6:35
Above value I need to convert in sqlite query like below..
Local 9 3:55 4:50
Local 12 4:20 5:15
Local 9 4:40 5:35
Local 12 5:00 5:55
Local 9 5:20 6:15
Local 9 5:40 6:35
Oh, so you're stuck with a terrible DB design which you aren't allowed to change... that sucks. It ought to be divided into 4 tables (at least). Anyway, here is one way to do it in this particular case.
I assume the first query is equivalent to this:
SELECT id, F1, F2, F3, F4, F5, F6
FROM tablename
WHERE id IN (101,102,1,18)
So, you can do transposing/pivoting/whatever it's actually called like this:
SELECT
MAX(CASE WHEN id=101 THEN F1 END) R1,
MAX(CASE WHEN id=102 THEN F1 END) R2,
MAX(CASE WHEN id=1 THEN F1 END) R3,
MAX(CASE WHEN id=18 THEN F1 END) R4
FROM tablename
UNION
SELECT
MAX(CASE WHEN id=101 THEN F2 END) R1,
MAX(CASE WHEN id=102 THEN F2 END) R2,
MAX(CASE WHEN id=1 THEN F2 END) R3,
MAX(CASE WHEN id=18 THEN F2 END) R4
FROM tablename
UNION
SELECT
MAX(CASE WHEN id=101 THEN F3 END) R1,
MAX(CASE WHEN id=102 THEN F3 END) R2,
MAX(CASE WHEN id=1 THEN F3 END) R3,
MAX(CASE WHEN id=18 THEN F3 END) R4
FROM tablename
UNION
SELECT
MAX(CASE WHEN id=101 THEN F4 END) R1,
MAX(CASE WHEN id=102 THEN F4 END) R2,
MAX(CASE WHEN id=1 THEN F4 END) R3,
MAX(CASE WHEN id=18 THEN F4 END) R4
FROM tablename
UNION
SELECT
MAX(CASE WHEN id=101 THEN F5 END) R1,
MAX(CASE WHEN id=102 THEN F5 END) R2,
MAX(CASE WHEN id=1 THEN F5 END) R3,
MAX(CASE WHEN id=18 THEN F5 END) R4
FROM tablename
UNION
SELECT
MAX(CASE WHEN id=101 THEN F6 END) R1,
MAX(CASE WHEN id=102 THEN F6 END) R2,
MAX(CASE WHEN id=1 THEN F6 END) R3,
MAX(CASE WHEN id=18 THEN F6 END) R4
FROM tablename
Unfortunately, it's sorted in a strange way.
And I really advise you to persuade someone in charge to re-design the DB. Some designers think that having tables with such structure is "flexible" and "improves performance", but it's not so: doing actual work with such tables requires highly non-trivial queries, which most of DBMSs cannot optimize because they were never expected to deal with such atrocities.
Such tables also break the very idea of the relational model. Each table must have one-statement "template", for example, CREATE TABLE S (id INTEGER, name TEXT, address TEXT) can have template "A supplier with id ID is called NAME and is located at ADDRESS". Now, each row in this table yields you a true statement about the world when you put its contents into the template: if S would contain a row (1, "Bob & Co.", "Lime St., 125"), then it would tell you that "A supplier with id 1 is called Bob & Co. and is located at Lime St., 125".
All relational operations: selection, projection, joins, filtering, etc. don't just combine tables in a particular way, no! They also combine "templates", so you can say what exactly information a query gives you. And vice versa, if you can express what information you want through combining those "templates", it would almost automatically give you a corresponding query.
And the table you have to work with can be associated with no sane "template". That's why you have to write nonsensical queries in order to get something useful. Note that I can basically guess the "template" of the resulting set,
R1 R2 R3 R4
============================
Local 9 3:55 4:50
...
It's something like "An event of type R2 was happening at place R1, starting at time R3 and ending at time R4". Am I correct?
Related
I want to add this query in stored procedure but it gives an error: ORA-00913: too many values
Select SUM(CONNMASS.CONN_BILLAMOUNT) as Revenuebilled,
count(CONNMASS.CONN_BILLEDUNITS) AS volumebilled,
count(MASSBILL.BM_lo_id) as normalbilled,
( SELECT COUNT(CASE WHEN SRM_DISCON_STATUS_ID = 3 THEN 1 END) AS ACTIVE_CONNECTIONS,
COUNT(CASE WHEN SRM_DISCON_STATUS_ID = 2 THEN 1 END) AS DISC_CONNECTIONS
from Connection_master)
from CONNECTION_MASTER CONNMASS
left join BILLING_MASTER MASSBILL
on MASSBILL.CONN_SERVICE_NO = CONNMASS.CONN_SERVICE_NO;
The problem is that you are selecting multiple values in the sub-query. You can only select a single value in a sub-query in the SELECT clause.
However, you do not need the sub-query and appear to want:
Select SUM(CONNMASS.CONN_BILLAMOUNT) as Revenuebilled,
count(CONNMASS.CONN_BILLEDUNITS) AS volumebilled,
count(MASSBILL.BM_lo_id) as normalbilled,
COUNT(CASE SRM_DISCON_STATUS_ID WHEN 3 THEN 1 END) AS ACTIVE_CONNECTIONS,
COUNT(CASE SRM_DISCON_STATUS_ID WHEN 2 THEN 1 END) AS DISC_CONNECTIONS
from CONNECTION_MASTER CONNMASS
left join BILLING_MASTER MASSBILL
on MASSBILL.CONN_SERVICE_NO = CONNMASS.CONN_SERVICE_NO;
If you did want the sub-queries then:
Select SUM(CONNMASS.CONN_BILLAMOUNT) as Revenuebilled,
count(CONNMASS.CONN_BILLEDUNITS) AS volumebilled,
count(MASSBILL.BM_lo_id) as normalbilled,
( SELECT COUNT(CASE SRM_DISCON_STATUS_ID WHEN 3 THEN 1 END)
from Connection_master) AS ACTIVE_CONNECTIONS,
( SELECT COUNT(CASE SRM_DISCON_STATUS_ID WHEN 2 THEN 1 END)
from Connection_master) AS DISC_CONNECTIONS
from CONNECTION_MASTER CONNMASS
left join BILLING_MASTER MASSBILL
on MASSBILL.CONN_SERVICE_NO = CONNMASS.CONN_SERVICE_NO;
Need your expertise in writing an SQL for the below scenario
I have a single row in a table "range_num" as follows.
start_num end_num
10 14
Is there any way we can write a query to find all the gaps between 10 and 14 i ..e 11,12,13 in the below format
col1 col2 col3 col4 col5
10 11 12 13 14
I am using Teradata databases , so any compliant SQL query will be of great help!!
Here is solution for your problem...
select
max(case when rownum=1 then gap end) as col1,max(case when rownum=2 then gap end) as col2,
max(case when rownum=3 then gap end) as col3,max(case when rownum=4 then gap end) as col4,
max(case when rownum=5 then gap end) as col5,max(case when rownum=6 then gap end) as col6,
max(case when rownum=7 then gap end) as col7,max(case when rownum=8 then gap end) as col8,
max(case when rownum=9 then gap end) as col9,max(case when rownum=10 then gap end) as col10,
max(case when rownum=11 then gap end) as col11,max(case when rownum=12 then gap end) as col12,
max(case when rownum=13 then gap end) as col13,max(case when rownum=14 then gap end) as col14,
max(case when rownum=15 then gap end) as col15,max(case when rownum=16 then gap end) as col16,
max(case when rownum=17 then gap end) as col17,max(case when rownum=18 then gap end) as col18,
max(case when rownum=19 then gap end) as col19,max(case when rownum=20 then gap end) as col20,
max(case when rownum=21 then gap end) as col21,max(case when rownum=22 then gap end) as col22,
max(case when rownum=23 then gap end) as col23
from
(
select a.id_start,
b.day_of_calendar as gap,
csum(1,1) as rownum
from db_sok.testt a,
sys_calendar.calendar b
where b.day_of_calendar between a.id_start and a.id_end
)X
do a little tweaking in case you need something else...:)
i wanna change some rows to columns.
This is a example how i have my database now
And i wanna change it by
But i'm using a ODBC connection, if you could help me with a useful example or code guide i'll appreciate it.
Thanks
You can use a MAX/CASE "manual pivot" that should work on most (all?) SQL databases, something like;
SELECT "datetime",
MAX(CASE WHEN bsc='bsccc2' THEN ineffective_attempts END) bsccc2,
MAX(CASE WHEN bsc='bsccc3' THEN ineffective_attempts END) bsccc3,
MAX(CASE WHEN bsc='bsccc4' THEN ineffective_attempts END) bsccc4,
MAX(CASE WHEN bsc='bscmb2' THEN ineffective_attempts END) bscmb2,
MAX(CASE WHEN bsc='bscmbo' THEN ineffective_attempts END) bscmbo,
MAX(CASE WHEN bsc='bscva2' THEN ineffective_attempts END) bscva2
FROM mytable
GROUP BY "datetime"
ORDER BY "datetime"
Depending on the underlying database, you may want to change the quoting of the datetime identifier (or possibly rename the field to avoid needing to quote it).
please read carefully and if you do not understand what I am saying please let me know.
Below are the tables names and the columns in those tables
table: SYSTEM_USER_SKILL
user_id
skill_id
user_abilities
table: SYSTEM_ADMIN_SKILL
skill_id
skill_name
table: SYSTEM_USER
user_id
user_full_name
I want to write a dynmanic sql or a pl/sql which will display the user_full_name and user_ability.
but I want it to display like this:
p.s. where you see the "Y" and "N" those are results from user_abilities
I dont know how to do this all i know is that it can be done with dynamic sql or pl/sql
Getting the data in tabular form can be done with a pivot, as long as you're on Oracle 11gR2:
select * from (
select su.user_full_name, sas.skill_name, sus.user_abilities
from system_user su
cross join system_admin_skill sas
left join system_user_skill sus on sus.user_id = su.user_id
and sus.skill_id = sas.skill_id
) pivot (max(user_abilities) as able for (skill_name)
in ('php' as php, 'java' as java, 'pl/sql / sql' as plsql_sql,
'Oracle apex' as oracle_apex));
USER_FULL_NAME PHP_ABLE JAVA_ABLE PLSQL_SQL_ABLE ORACLE_APEX_ABLE
-------------------- -------- --------- -------------- ----------------
Sarah woods N N Y Y
John brown N Y Y Y
Johnny paterson Y Y Y Y
Amy brown N N Y N
but you need to list each skill explicitly in the in clause. SQL Fiddle.
In SQL*Plus or SQL Developer you could get the headings you want with something like:
column user_full_name heading "Name"
column php_able format a15 heading "php"
column java_able format a15 heading "java"
column plsql_sql_able format a15 heading "pl/sql / sql"
column oracle_apex_able format a15 heading "Oracle apex"
select ...
Name php java pl/sql / sql Oracle apex
-------------------- --------------- --------------- --------------- ---------------
Sarah woods N N Y Y
John brown N Y Y Y
Johnny paterson Y Y Y Y
Amy brown N N Y N
... but I have no idea if Toad has anything similar.
The non-pivot equivalent of this, which you would have had to use in older versions, would be something like:
select su.user_id, su.user_full_name,
max(case when sas.skill_id = 1 then sus.user_abilities end) as php,
max(case when sas.skill_id = 2 then sus.user_abilities end) as java,
max(case when sas.skill_id = 3 then sus.user_abilities end) as plsql_sql,
max(case when sas.skill_id = 4 then sus.user_abilities end) as oracle_apex
from system_user su
cross join system_admin_skill sas
left join system_user_skill sus on sus.user_id = su.user_id
and sus.skill_id = sas.skill_id
group by su.user_id, su.user_full_name;
This still has all the skills hard-coded in. To allow for additional skills without having to modify the query you'd need to build it dynamically, as shown in earlier answers linked to in comments. In this specific case you could do something like:
create or replace function get_skill_matrix return sys_refcursor as
query varchar2(32767);
rc sys_refcursor;
begin
query := 'select su.user_id, su.user_full_name';
for tmp in (select skill_id, skill_name from system_admin_skill
order by skill_id)
loop
query := query || ', max(case when sas.skill_id = ' || tmp.skill_id
|| ' then sus.user_abilities end) as "'
|| substr(tmp.skill_name, 1, 30) || '"';
end loop;
query := query || ' from system_user su';
query := query || ' cross join system_admin_skill sas';
query := query || ' left join system_user_skill sus on sus.user_id = su.user_id';
query := query || ' and sus.skill_id = sas.skill_id';
query := query || ' group by su.user_id, su.user_full_name';
open rc for query;
return rc;
end;
/
The query string used for the dynamic SQL is just built up to look exactly the same as the static version, but with each skill_id-specific clause generated in a loop from the base system_admin_skill table.
When you call this function you get a cursor back. You haven't really said how or where you're using the results. You can treat it as a result set in a Java program, for example, by executing the function and then calling getCursor() on the statement object. In SQL*Plus or SQL Developer you can use the variable and print commands to display it:
var rc refcursor;
exec :rc := get_skill_matrix;
print rc
In SQL Developer that gives:
anonymous block completed
RC
----------------------------------------------------------------------------------------------
USER_ID USER_FULL_NAME java php pl/sql / sql Oracle apex
--------------------------------------- -------------------- ---- --- ------------ -----------
3 Amy brown N N Y N
4 Sarah woods N N Y Y
2 Johnny paterson Y Y Y Y
1 John brown Y N Y Y
Or in SQL*Plus, where you can do column user_id noprint to hide the ID (which I've included in case two people have the same name!):
Name j p p O
-------------------- - - - -
Amy brown N N Y N
Sarah woods N N Y Y
Johnny paterson Y Y Y Y
John brown Y N Y Y
In Toad I think you can do this, which is all the exec is doing anyway:
begin
:rc := get_skill_matrix;
end;
... and it'll prompt you for the bind type for :rc; if you pick 'ref cursor' it'll show the results in the data grid. Apparently.
OK, same thing but without a function (but still PL/SQL), and including the skill ID in the column alias before truncating to make it unique:
var rc refcursor
declare
query varchar2(32767);
begin
query := 'select su.user_id, su.user_full_name as "Name"';
for tmp in (select skill_id, skill_name from system_admin_skill
order by skill_id) loop
query := query || ', max(case when sas.skill_id = ' || tmp.skill_id
|| ' then sus.user_abilities end) as "'
|| substr(tmp.skill_id || ' ' || tmp.skill_name, 1, 30) || '"';
end loop;
query := query || ' from system_user su';
query := query || ' cross join system_admin_skill sas';
query := query || ' left join system_user_skill sus on sus.user_id = su.user_id';
query := query || ' and sus.skill_id = sas.skill_id';
query := query || ' group by su.user_id, su.user_full_name';
open :rc for query;
end;
/
print rc
Which gives:
RC
-----------------------------------------------------------------------------
USER_ID Name 1 java 2 php 3 pl/sql / sql 4 Oracle apex
-------------- -------------------- ------ ----- -------------- -------------
3 Amy brown N N Y N
4 Sarah woods N N Y Y
2 Johnny paterson Y Y Y Y
1 John brown Y N Y Y
Lab Test Name Source Collected Date Results
Urea 6/4/2013 12:00:00 AM 5
Uric Acid 6/4/2013 12:00:00 AM 10
Cholesterol 6/3/2013 12:00:00 AM 25
I have a datatable with above values.
I need to pivot it to following structure:
Urea Uric Acid Cholesterol
6/4/2013 12:00:00 AM 5 10 -
6/3/2013 12:00:00 AM - - 25
If you look at the answer linked by Mikael, you'll realize that you will need to build the columns for your pivot statement dynamically since the PIVOT syntax doesn't allow a subselect within the FOR clause. So essentially you need to do something like this:
DECLARE
#cols AS NVARCHAR(MAX),
#y AS INT,
#sql AS NVARCHAR(MAX);
-- Construct the column list for the IN clause
-- e.g., [Urea],[Uric Acid],[Cholesterol]
SET #cols = STUFF(
(SELECT N',' + QUOTENAME(y) AS [text()]
FROM (SELECT DISTINCT (LabTestName) AS y FROM YourTable) AS Y
ORDER BY y
FOR XML PATH('')),
1, 1, N'');
You can now build your PIVOT statement as so:
set #SQL = N'
SELECT SourceCollectedDate,'+#cols+N'
FROM YourTable
PIVOT (
SUM(results) FOR LabTestName IN ( '+#cols+N')
) AS PivotTable
ORDER BY SourceCollectedDate desc
'
And execute it:
EXEC sp_executesql #sql
Which will produce:
SourceCollectedDate Urea Uric Acid Cholesterol
2013-06-04 00:00:00.000 5 10 NULL
2013-06-03 00:00:00.000 NULL NULL 25
Just note that my example has YourTable as the table name. You need to replace that with your actual table name.
SQL Fiddle (Based off of what Chad created)
Here's a solution that doesn't require pivot or dynamic SQL. The tradeoff is that you need to specify each possible Lab Test Name in your query.
SELECT [Source Collected Date],
MAX(CASE WHEN [Lab Test Name] = 'Urea'
THEN Results ELSE NULL END) AS Urea,
MAX(CASE WHEN [Lab Test Name] = 'Uric Acid'
THEN Results ELSE NULL END) AS [Uric Acid],
MAX(CASE WHEN [Lab Test Name] = 'Cholesterol'
THEN Results ELSE NULL END) AS Cholesterol
FROM Table1
GROUP BY [Source Collected Date]
See it working here.