PIVOT in SQLIte - sqlite
I'd like to get a table which shows parameters and values they receive for all of their parametervalues in one query.
This is my table structure:
tbl_parameter
parameterid
parametername
tbl_parametervalues
parameterid
parametervalue
Actual Structure in tbl_parameter
--------------------------------
----------------------------------
| parameterid | parametername |
|----------------------------
| TYPE | Type |
| TEMP | Temp(Deg.C) |
| TIME | Time |
| DATE | Date |
| TECHNICIAN | Technician |
| TESTLENGTH | Test Length |
| TESTRESULT | Test Result |
-----------------------------------
Actual Structure in tbl_parametervalues
------------------------------------
| parameterid | parametervalue |
|----------------------------
| TYPE | DW1 |
| TEMP | 21 |
| TIME | 10:45 PM |
| DATE | 14/09/2011 |
| TECHNICIAN | Test1 |
| TESTLENGTH | 12 |
| TESTRESULT | Pass |
| TYPE | DW2 |
| TEMP | 22 |
| TIME | 11:45 PM |
| DATE | 15/09/2011 |
| TECHNICIAN | Test2 |
| TESTLENGTH | 12 |
| TESTRESULT | Pass
-----------------------------------
I want the result set to look like this:
-----------------------------------------------------------------------------
| SL NO | Type | Temp | Time | Date | Technician | Test |Test |
| | Length |Result |
---------------------------------------------------------------------------
| 1 | DW1 | 21 |10:45 PM|14/09/2011| Test1 | 12 | Pass |
| 2 | DW2 | 22 |11.45 | 15/09/2011| Test2 | 12 | Pass |
|------------------------------------------------------------------------------
How can I accomplish this in SQLite?
I could not find a definition of how to detect sets of parameter values, i.e. which "TEMP" belongs to which "TYPE". So I assume that the sets of parameter values are always entered into the database consecutively and in the order given in the question. The comment by OP seems to allow this assumption. It is not very complicated (though a little) to immplement some robustness against shuffled orders (by associating via a detour by the parameterids), but I hope it is not necessary.
I also could not find information of what "SL NO" means and where the value is coming from. So I fake it by dividing the rowid of the TESTRESULT value by 7 (the number of different parameter names, which I consider to be the size of a parameter set). It should not be hard to dig the correct values up from your database. It is not required that the rowids are on multiples of 7, as long as the parameters are entered consecutively. Just the "SL NO" might skip a few numbers, if the rowids of e.g. "TYPE" are multiples of e.g. 8, otherwise the query tolerates gaps between parameter sets.
You can find the non-query part of my MCVE at the end of this answer.
Query:
select
'SL NO',
TYPE.parametername,
TEMP.parametername,
TIME.parametername,
DATE.parametername,
TECHNICIAN.parametername,
TESTLENGTH.parametername,
TESTRESULT.parametername
from
parameter TYPE,
parameter TEMP,
parameter TIME,
parameter DATE,
parameter TECHNICIAN,
parameter TESTLENGTH,
parameter TESTRESULT
where TYPE.parameterid='TYPE'
and TEMP.rowid=TYPE.rowid+1
and TIME.rowid=TYPE.rowid+2
and DATE.rowid=TYPE.rowid+3
and TECHNICIAN.rowid=TYPE.rowid+4
and TESTLENGTH.rowid=TYPE.rowid+5
and TESTRESULT.rowid=TYPE.rowid+6
UNION ALL
select
TESTRESULT.rowid/7,
TYPE.parametervalue,
TEMP.parametervalue,
TIME.parametervalue,
DATE.parametervalue,
TECHNICIAN.parametervalue,
TESTLENGTH.parametervalue,
TESTRESULT.parametervalue
from
parametervalues TYPE,
parametervalues TEMP,
parametervalues TIME,
parametervalues DATE,
parametervalues TECHNICIAN,
parametervalues TESTLENGTH,
parametervalues TESTRESULT
where TYPE.parameterid='TYPE'
and TEMP.rowid=TYPE.rowid+1
and TIME.rowid=TYPE.rowid+2
and DATE.rowid=TYPE.rowid+3
and TECHNICIAN.rowid=TYPE.rowid+4
and TESTLENGTH.rowid=TYPE.rowid+5
and TESTRESULT.rowid=TYPE.rowid+6
;
make one table on the fly for each pivot column
select from each of those tables the entry for one column
associate entries for the same line via assumptions (as stated above) on rowids
Output:
SL NO Type Temp(Deg.C) Time Date Technician Test Length Test Result
1 DW1 21 10:45 PM 14/09/2011 Test1 12 Pass
2 DW2 22 11.45 15/09/2011 Test2 12 Pass
MCVE (.dump):
BEGIN TRANSACTION;
CREATE TABLE parametervalues(parameterid varchar(30), parametervalue varchar(30) );
INSERT INTO parametervalues(parameterid,parametervalue) VALUES('TYPE','DW1');
INSERT INTO parametervalues(parameterid,parametervalue) VALUES('TEMP','21');
INSERT INTO parametervalues(parameterid,parametervalue) VALUES('TIME','10:45 PM');
INSERT INTO parametervalues(parameterid,parametervalue) VALUES('DATE','14/09/2011');
INSERT INTO parametervalues(parameterid,parametervalue) VALUES('TECHNICIAN','Test1');
INSERT INTO parametervalues(parameterid,parametervalue) VALUES('TESTLENGTH','12');
INSERT INTO parametervalues(parameterid,parametervalue) VALUES('TESTRESULT','Pass');
INSERT INTO parametervalues(parameterid,parametervalue) VALUES('TYPE','DW2');
INSERT INTO parametervalues(parameterid,parametervalue) VALUES('TEMP','22');
INSERT INTO parametervalues(parameterid,parametervalue) VALUES('TIME','11.45');
INSERT INTO parametervalues(parameterid,parametervalue) VALUES('DATE',' 15/09/2011');
INSERT INTO parametervalues(parameterid,parametervalue) VALUES('TECHNICIAN','Test2');
INSERT INTO parametervalues(parameterid,parametervalue) VALUES('TESTLENGTH','12');
INSERT INTO parametervalues(parameterid,parametervalue) VALUES('TESTRESULT','Pass');
CREATE TABLE parameter (parameterid varchar(30), parametername varchar(30));
INSERT INTO parameter(parameterid,parametername) VALUES('TYPE','Type');
INSERT INTO parameter(parameterid,parametername) VALUES('TEMP','Temp(Deg.C)');
INSERT INTO parameter(parameterid,parametername) VALUES('TIME','Time');
INSERT INTO parameter(parameterid,parametername) VALUES('TATE','Date');
INSERT INTO parameter(parameterid,parametername) VALUES('TECHNICIAN','Technician');
INSERT INTO parameter(parameterid,parametername) VALUES('TESTLENGTH','Test Length');
INSERT INTO parameter(parameterid,parametername) VALUES('TESTRESULT','Test Result');
COMMIT;
Note1:
I skipped the line breaks for the headers of the "Test *" parameter names. That seems irrelevant.
Note2:
My MCVE contains values to match the desired output, not always identical to the sample input. If the values are taken from sample input, the output looks different - and more convincing. It is not important which side of the inconsistence is correct and which is the typo. I chose to implement the version which requires more flexibility.
Related
How to select the next 50 records from a specified row in an SQLite table
Consider that my SQLite table has the following schema, |''''''''''''''''''''''''''''''''''''' | unique_id(TXT) | object_data(BLOB) | |''''''''''''''''''''''''''''''''''''' | | | | | | | | | '''''''''''''''''''''''''''''''''''''' Assume that the row_id property is enabled, and so my question is, for a given unique_id, is it possible to fetch the next 50 records from the table, using a single SQL query? (Using the row_id property)
Try getting result through this method. Select * from table_name [WHERE conditions] Limit 50 offset (Select row_id from table_name where unique_id = x);
ms access: give a date in a table how do I create a from_date and to_date field in a query
MS Access. I'm querying a table that displays a client_name, release_name, release_date for a number of clients and releases. I'm trying to write a query that returns the following data for one client: client_name, release_name, from_release_date, to_release_date. In this case the from_release_date is the original release_date from the underlying table but the new field in the query to_release_date is the day before the next release was installed. For example: +-------------+-----------+-------------------+-------------------+ | client_name | release | from_release_date | to_release date | +-------------+-----------+-------------------+-------------------+ | client A | release 1 | 01/01/2017 | 01/02/2017 | | client A | release 2 | 02/02/2017 | 02/03/2017 | | client A | release 3 | 03/03/2017 | | +-------------+-----------+-------------------+-------------------+ How do I create this 'to_release_date' field?
Use a subquery: Select client_name, release_name, release_date As from_release_date, (Select Top 1 DateAdd("d", -1, T.release_date) From YourTable As T Where T.client_name = YourTable.client_name And T.release_date > YourTable.release_date Order By T.release_date Desc) As to_release_date From YourTable
SQLite: How to extract primary keys and unique constraints with correct names
Given a SQLite db. a table with primary key: create table t1 (id int not null, CONSTRAINT pk_id PRIMARY KEY (id)); Now query info for it: PRAGMA TABLE_INFO(t1); returns: | cid | name | type | notnull | dflt_value | pk | | --- | ---- | ---- | ------- | -----------| -- | | 0 | id | int | 1 | <null> | 1 | PRAGMA index_list(t1); returns: | seq | name | unique | origin | partial | | --- | ----------------------| ------ | ------ | ------- | | 0 | sqlite_autoindex_t1_1 | 1 | pk | 0 | As we can see index_list returns info about the PK but it reports incorrect name ("sqlite_autoindex_t1_1" instead of "pk_t1"). The same problem with UNIQUE constraints. They are created with autogenerated names. Is it possible to extract real PRIMARY KEY/UNIQUE CONSTRAINT name? P.S. I can see that JetBrains's DataGrip correctly show PK names in database browser. But sqliteadmin for example shows them with name like sqlite_autoindex_t1_1. For unique constraints even DataGrip doesn't show correct names (actually it doesn't show them at all).
The index and the constraint are different objects. SQLite has no mechanism to retrieve the constraint name. You'd have to parse the SQL.
sqlite extract two row from two tables to create a new table
I have an sqlite db with two table table1 ------------------------------ TIME | ElevationA| ElevationB| -----|-----------|-----------| T1 | eA1 | eB1 | T2 | eA2 | eB2 | table2 ------------------------------ TIME | Temperat A| Temperat B| -----|-----------|-----------| T1 | tA1 | tB1 | T2 | tA2 | tB2 | I am searching for a "magic" command that make a table of all parameter at a given time, e.g something that would be like: SELECT WHERE TIME=T1 table1 AS ELEV ,table2 AS TEMP and that would result in table3 ------------ ELEV | TEMP | -----|----- | eA1 | tA1 | eB1 | tB1 | Of course I could bash script it but I would prefer a to create a view in SQLite as it is more straightforwards and avoid to duplicate the data. Any idea welcome
You can use: CREATE TABLE TABLE3(ELEV,TEMP); INSERT INTO TABLE3(ELEV,TEMP) VALUES((SELECT TIME FROM TABLE1 WHERE TIME = T1),SELECT TIME FROM TABLE2 WHERE TIME =T2)); These 2 select clauses must return the same number of records.
sqlite combining select results for searching
Alright so here are my two tables. CREATE TABLE [cards] ( [id] TEXT PRIMARY KEY, [game_id] TEXT NOT NULL, [set_id] TEXT CONSTRAINT [id_set_id] REFERENCES [sets]([id]) ON DELETE CASCADE ON UPDATE CASCADE MATCH SIMPLE NOT DEFERRABLE INITIALLY IMMEDIATE, [name] TEXT NOT NULL, [image] TEXT NOT NULL); CREATE TABLE [custom_properties] ( [id] TEXT PRIMARY KEY, [card_id] TEXT CONSTRAINT [id_card_id] REFERENCES [cards]([id]) ON DELETE CASCADE ON UPDATE CASCADE MATCH SIMPLE NOT DEFERRABLE INITIALLY IMMEDIATE, [game_id] TEXT CONSTRAINT [id_game_id4] REFERENCES [games]([id]) ON DELETE CASCADE ON UPDATE CASCADE MATCH SIMPLE NOT DEFERRABLE INITIALLY IMMEDIATE, [name] TEXT NOT NULL, [type] INTEGER NOT NULL, [vint] INTEGER, [vstr] TEXT); What I would like to do is to have a search that grabs all the data from the cards row, and then adds the column who's name is (where custom_properties.card_id == cards.id).name. Then I would like it's value to be vint if type == 1, else vstr. So, here is an example dataset cards |id | game_id | set_id | name | image| +---+---------+--------+------+------+ | a | asdf | fdsaf |loler | blah | +------------------------------------+ custom_properties | id | card_id | game_id | name | type | vint | vstr | +----+---------+---------+------+------+------+------+ | f | a | asdf | range| 1 | 12 | | | b | a | asdf | rank | 0 | | face | +----+---------+---------+------+------+------+------+ the resulting table would look like this, where the columns range and rank are derived from custom_properties.name |id | game_id | set_id | name | image | range | rank | +---+---------+--------+------+-------+-------+------+ |a | asdf | fdsaf | loler| blah | 12 | face | +---+---------+--------+------+-------+-------+------+
try this: SELECT Cards.id, Cards.game_id, Cards.set_id, Cards.name, Cards.id, Cards.image, CASE WHEN Custom_Properties.type = 1 THEN Custom_Properties.vint ELSE Custom_Properties.vstr END as Range Custom_Properties.vstr as rank FROM Cards INNER JOIN Custom_Properties ON Cards.id = Custom_Properties.card_ID WHERE Cards.Name = 'loller'
It's not actually possible to do this.