query specific table columns - postgresql

I have table with specific column names. They have the prefix 'file_'.
For example:
Column Name
Value
name
somename
date
2000-01-01
size
15
file_type1
1
file_type2
34
.....
....
file_typeN
12
The file types columns 'file_typeN' can be added by another team to table (even may be deleted).
So I want to create sql query to select only values for columns with prefix 'file_'.
The one query for the table my_files_description_table, which can have different number of columns with 'file_' prefix.
Something like:
select <only columns with 'file_' prefix> from my_files_description_table;
I can query all columns with 'file_' prefix:
SELECT column_name FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 'my_files_description_table' and column_name like 'file_%';
But I don't know what to do with that.
I need the query that for this table
Column Name
Value
name
somename
date
2000-01-01
size
15
file_type1
1
file_type2
34
should return
Column Name
Value
file_type1
1
file_type2
34
And for this table
Column Name
Value
name
somename
date
2000-01-01
size
15
file_type1
2
file_type2
5
file_type3
134
file_type4
12
should return
Column Name
Value
file_type1
2
file_type2
5
file_type3
134
file_type4
12
I use PostgreSQL 9.6.

Related

Is it possible in Postgresql to use one column as source of names of columns?

Suppose that we have table with field ID, type, Date, any_value
Suppose we have such values in a table (select * from my_table):
ID type date any_value
1 alfa 2022-01-01 50
2 beta 2022-01-01 70
3 alfa 2022-01-02 111
4 beta 2022-01-02 444
...
Is it possible to create a query with a such result (if it is - how I may do it?):
date alfa beta
2022-01-01 50 70
2022-01-02 111 444
....
Of course it should be performed automatically, not by making the simplest "left join" for each column (as the number of values in "type" column may be different in May , different in July- and it should be only one query.
(if it would be "gamma" in "type" column, then it should be "gamma" column after beta column, if "delta" - then "delta")

KDB/Q: Get sum of a certain column value

I want to create a column that equals the sum of the value in another column (colA) when the value of another column (colB) equal something.
Without the condition, I can get the sum of all values in colA by using:
update TotalVal: sum colB by date from myTable
I tried to achieve what I want by using
update GOT: sum colB by date from myTable where colA in (`abc,`edf)
This creates the correct values for GOT, but the GOT column only has value where colA is abc or edf. This is not what I really want.
To visualise, what I want is the column WANTED
date colA colB GOT WANTED
2020.08.17 abc 5 13 13
2020.08.17 mom 7 13
2020.08.17 xyz 8 13 13
2020.08.17 tuf 9 13
I just fixed it myself by
update (GOT: sum colB where colA in (`abc,`edf)) by date from myTable

sql - Postgresql, increment column based on other column values

I have table like
create table test(employee integer NOT NULL, code character varying(200), number integer)
I want to auto increment column 'number' on every insert record
insert into test(employee, code) values(17,'bangalore')
insert into test(employee, code) values(17,'bangalore')
insert into test(employee, code) values(17,'mumbai')
I want result like
employee code number
17 bangalore 1
17 bangalore 2
17 bangalore 3
17 mumbai 1
17 mumbai 2
17 bangalore 4
17 mumbai 3
18 bangalore 1
18 bangalore 2
18 mumbai 1
18 mumbai 2
For a batch upload of data, try if below approach would be useful.
create a temporary table test2
create table test2(employee integer NOT NULL, code character varying(200))
insert into test2(employee, code) values(17,'bangalore')
insert into test2(employee, code) values(17,'bangalore')
insert into test2(employee, code) values(17,'mumbai')
Insert into actual table along with incremental number
insert into test(employee, code, number)
select employee, code, row_number() over (partition by code ) from test2
You could include order by clause like primary key column or another column like created_date :
over (partition by code order by created_date)
create table test (employee integer NOT NULL, code character varying(200), number integer)
insert into test(employee, code, number ) values(17,'bangalore',(select coalesce(max(number) + 1,1) from test where employee = 17 and code = 'bangalore'));
insert into test(employee, code, number ) values(17,'bangalore',(select coalesce(max(number) + 1,1) from test where employee = 17 and code = 'bangalore'));
insert into test(employee, code, number ) values(17,'mumbai',(select coalesce(max(number) + 1,1) from test where employee = 17 and code = 'mumbai'));

kdb: dynamically denormalize a table (convert key values to column names)

I have a table like this:
q)t:([sym:(`EURUSD`EURUSD`AUDUSD`AUDUSD);server:(`S01`S02`S01`S02)];volume:(20;10;30;50))
q)t
sym server| volume
-------------| ------
EURUSD S01 | 20
EURUSD S02 | 10
AUDUSD S01 | 30
AUDUSD S02 | 50
I need to de-normalize it to display the data nicely. The resulting table should look like this:
sym | S01 S02
------| -------
EURUSD| 20 10
AUDUSD| 30 50
How do I dynamically convert the original table using distinct values from server column as column names for the new table?
Thanks!
Basically you want 'pivot' table. Following page has a very good solution for your problem:
http://code.kx.com/q/cookbook/pivoting-tables/
Here are the commands to get the required table:
q) P:asc exec distinct server from t
q) exec P#(server!volume) by sym:sym from t
One tricky thing around pivoting a table is - the keys of the dictionary should be of type symbol otherwise it won't generate the pivot table structure.
E.g. In the following table, we have a column dt with type as date.
t:([sym:(`EURUSD`EURUSD`AUDUSD`AUDUSD);dt:(0 1 0 1+.z.d)];volume:(20;10;30;50))
Now if we want to pivot it with columns as dates , it will generate a structure like :
q)P:asc exec distinct dt from t
q)exec P#(dt!volume) by sym:sym from t
(`s#flip (enlist `sym)!enlist `s#`AUDUSD`EURUSD)!((`s#2018.06.22 2018.06.23)!30j, 50j;(`s#2018.06.22 2018.06.23)!20j, 10j)
To get the dates as the columns , the dt column has to be typecasted to symbol :
show P:asc exec distinct `$string date from t
`s#`2018.06.22`2018.06.23
q)exec P#((`$string date)!volume) by sym:sym from t
sym | 2018.06.22 2018.06.23
------| ---------------------
AUDUSD| 30 50
EURUSD| 20 10

need help writing a date sensitive T-SQL query

I need help writing a T-SQL query that will generate 52 rows of data per franchise from a table that will often contain gaps in the 52 week sequence per franchise (i.e., the franchise may have reported data bi-weekly or has not been in business for a full year).
The table I'm querying against looks something like this:
FranchiseId | Date | ContractHours | PrivateHours
and I need to join it to a table similar to this:
FranchiseId | Name
The output of the query needs to look like this:
Name | Date | ContractHours | PrivateHours
---- ---------- ------------- ------------
AZ1 08-02-2011 292 897
AZ1 07-26-2011 0 0 -- default to 0's for gaps in sequence
...
AZ1 08-03-2010 45 125 -- row 52 for AZ1
AZ2 08-02-2011 382 239
...
AZ2 07-26-2011 0 0 -- row 52 for AZ2
I need this style of output for every franchise, i.e., 52 rows of data with default rows for any gaps in the 52 week sequence, in a single result set. Thus, if there are 100 franchises, the result set should be 5200 rows.
What I've Tried
I've tried the typical suggestions of:
Create a table with all possible dates
LEFT OUTER JOIN this to the table of data needed
The problems I'm running into are
ensuring that for every franchise their are 52 rows and
filling in gaps with the franchise name and 0 for hours, I can't
have the following in the result set:
Name | Date | ContractHours | PrivateHours
---- ---------- ------------- ------------
NULL 08-02-2011 NULL NULL
I don't know where to go from here? Is there an efficient way to write a T-SQL query that will produce the required output?
The bare bones is this
Generate 52 week ranges
Cross join with Franchise
LEFT JOIN the actual date
ISNULL to substitute zeroes
So, like this, untested
;WITH cDATE AS
(
SELECT
CAST('20100101' AS date /*smalldatetime*/) AS StartOfWeek,
CAST('20100101' AS date /*smalldatetime*/) + 6 AS EndOfWeek
UNION ALL
SELECT StartOfWeek + 7, EndOfWeek + 7
FROM cDATE WHERE StartOfWeek + 7 < '20110101'
), Possibles AS
(
SELECT
StartOfWeek, FranchiseID
FROM
cDATE CROSS JOIN Franchise
)
SELECT
P.FranchiseID,
P.StartOfWeek,
ISNULL(SUM(O.ContractHours), 0),
ISNULL(SUM(O.PrivateHours), 0)
FROM
Possibles P
LEFT JOIN
TheOtherTable O ON P.FranchiseID = O.FranchiseID AND
O.Date BETWEEN P.StartOfWeek AND P.EndOfWeek
GROUP BY
P.FranchiseID