index match in SQL - sql

Sorry in advance. I am very new in SQL. I don't know how to do a simple task like excel index match equivalent in SQL.
I have 2 tables in SQL (Please ignore the dash, I was using it to align the columns)
Table1
| Name | Limit1 || Limit2 |
| First | A || 05 |
| Second | B || 10 |
| Third | || 10 |
Table2
| Limit1Key|| Limit1Value || Limit2Key ||Limit2Value|
| A || 20,000 || 02 ||2,000,000 |
| B || 50,000 || 05 ||5,000,000 |
| || || 10 ||10,000,000 |
I want to get a final table looking like below.
Result Table
| Name || Limit1 || Limit2 |
| First || 20,000 || 5,000,000 |
| Second || 50,000 || 10,000,000 |
| Third || || 10,000,000 |
If there is already another post similar to this, please guide me to it.
Thank you!

If I understand correctly, you just want two joins:
select t1.*, t2_1.limit1value, t2_2.limit2_value
from table1 t1 left join
table2 t2_1
on t2_1.limit1key = t1.limit1 left join
table2 t2_2
on t2_2.limit2key = t1.limit2;

Related

Splunk: Combining multiple chart queries to get a single table

As on today we have two queries that are running 
1st query: Count of api grouped by apiName and status
index=aws* api.metaData.pid="myAppName"
| rename api.p as apiName
| chart count BY apiName "api.metaData.status"
| multikv forceheader=1
| table apiName success error NULL
which displays a table something like shown below
=====================================
| apiName|| success || error || NULL|
=====================================
| Test1 || 10 || 20 || 0 |
| Test2 || 10 || 20 || 0 |
| Test3 || 10 || 20 || 0 |
| Test4 || 10 || 20 || 0 |
| Test5 || 10 || 20 || 0 |
| Test6 || 10 || 20 || 0 |
2nd query : latency of api grouped by apiName
index=aws* api.metaData.pid="myAppName"
| rename api.p as apiName
| rename api.measures.tt as Response_Time
| chart min(Response_Time) as RT_fastest max(Response_Time) as RT_slowest by apiName
| table apiName RT_fastest RT_slowest
which displays a table something like below
======================================
| apiName || RT_fastest || RT_slowest|
======================================
| Test1 || 141 || 20 |
| Test2 || 10 || 20 |
| Test3 || 10 || 20 |
| Test4 || 0 || 20 |
| Test5 || 10 || 20 |
| Test6 || 10 || 20 |
Question:
If you see the above tables, both tables are grouped with apiName. Is there a way to combine these queries so that i get a single result something like this
|=================================================================|
| apiName || success || error || NULL || RT_fastest|| RT_slowest |
================================================================= |
| Test1 || 10 || 20. || 20. || 20. || 20. |
| Test2 || 10 || 20. || 20. || 20. || 20. |
| Test3 || 10 || 20. || 20. || 20. || 20. |
| Test4 || 10 || 20. || 20. || 20. || 20. |
| Test5 || 10 || 20. || 20. || 20. || 20. |
| Test6 || 10 || 20. || 20. || 20. || 20. |
 
I could not find any documentation regarding combining multiple chart query into one. Could someone please help me with this. Thanks :)
The challenge here is the two queries use different groupings - apiName and status in query1 and apiName alone in query2. Simply combining the two chart commands is not possible.
We can, however, append the second query to the first and then merge the results. Try this:
index=aws* api.metaData.pid="myAppName"
| rename api.p as apiName
| chart count BY apiName "api.metaData.status"
| multikv forceheader=1
| table apiName success error NULL
| append [ search index=aws* api.metaData.pid="myAppName"
| rename api.p as apiName
| rename api.measures.tt as Response_Time
| chart min(Response_Time) as RT_fastest max(Response_Time) as RT_slowest by apiName
| table apiName RT_fastest RT_slowest ]
| stats values(*) as * by apiName
| table apiName success error NULL RT_fastest RT_slowest

Big Query - Transpose arrays into colums

We have a table in Big Query like below.
Input table:
Name | Interests
-----+----------
Bob | ["a"]
Sue | ["a","b"]
Joe | ["b","c"]
We want to convert the above table to below format to make it BI/Visualisation friendly.
Target/Required table:
+------------------+
| Name | a | b | c |
+------------------+
| Bob | 1 | 0 | 0 |
| Sue | 1 | 1 | 0 |
| Joe | 0 | 1 | 0 |
+------------------+
Note: The Interests column is an array datatype. Is this sort of transformation possible in Big Query? If yes, Any reference query?
Thanks in advance!
Below is for BigQuery Standard SQL and uses scripting features of BQ
#standardSQL
create temp table ttt as (
select name, interest
from `project.dataset.table`,
unnest(interests) interest
);
EXECUTE IMMEDIATE (
SELECT """
SELECT name, """ ||
STRING_AGG("""MAX(IF(interest = '""" || interest || """', 1, 0)) AS """ || interest, ', ')
|| """
FROM ttt
GROUP BY name
"""
FROM (
SELECT DISTINCT interest
FROM ttt
ORDER BY interest
)
);
if to apply to sample data from your question - output is

How to concat data columns using loop?

How to concat columns data using loop in Postgres?
I have this table:
+------+------+------+--------+--------+--------+
| col1 | col2 | col3 | other1 | other2 | other3 |
+------+------+------+--------+--------+--------+
| 1 | 1 | 1 | 1 | 1 | 1 |
| 2 | 2 | 2 | 2 | 2 | 2 |
+------+------+------+--------+--------+--------+
and want to concat columns (col*).
Expected output:
+----------------+--------+--------+--------+
| concatedcolumn | other1 | other2 | other3 |
+----------------+--------+--------+--------+
| **1**1**1** | 1 | 1 | 1 |
| **2**2**2** | 2 | 2 | 2 |
+----------------+--------+--------+--------+
I can concat using:
select concat('**', col1, '**',col2, '**', col3, '**') as concatedcolumn
,other1, other2, other3
from sample_table
I have some 200 columns with prefix "col" and don't want to spell out all columns in sql. How could I achieve this with a loop?
Questionable database design aside, you can generate the SELECT statement dynamically:
SELECT 'SELECT concat_ws(''**'', '
|| string_agg(quote_ident(attname), ', ') FILTER (WHERE attname LIKE 'col%')
|| ') AS concat_col, '
|| string_agg(quote_ident(attname), ', ') FILTER (WHERE attname NOT LIKE 'col%')
|| ' FROM public.tbl;' -- your table name here
FROM pg_attribute
WHERE attrelid = 'public.tbl'::regclass -- ... and here
AND attnum > 0
AND NOT attisdropped;
db<>fiddle here
Query the system catalog pg_attribute or, alternatively, the information schema table columns. I prefer the system catalog.
Related answer on dba.SE discussing "information schema vs. system catalogs"
Execute in a second step (after verifying it's what you want).
No loop involved. You can build the statement dynamically, but you cannot (easily) return the result dynamically as SQL demands to know the return type at execution time.
concat_ws() is convenient, but it ignores NULL values. I didn't deal with those specially. You may or may not want to do that. Related:
Combine two columns and add into one new column
How to concatenate columns in a Postgres SELECT?

How to perform the same aggregation on every column, without listing the columns?

I have a table with N columns. Let's call them c1, c2, c3, c4, ... cN. Among multiple rows, I want to get a single row with COUNT DISTINCT(cX) for each X in [1, N].
c1 | c2 | ... | cn
0 | 4 | ... | 1
Is there a way I can do this (in a stored procedure) without writing every column name into the query manually?
Why?
We've had a problem where bugs in application servers mean we rewrite good column values with garbage inserted later. To solve this, I'm storing the information log-structure, where each row represents a logical UPDATE query. Then, when given a signal that the record is complete, I can determine if any values were (erroneously) overwritten.
An example of a single correct record in multiple rows: there is at most one value for each column.
| id | initialize_time | start_time | end_time |
| 1 | 12:00am | NULL | NULL |
| 1 | 12:00am | 1:00pm | NULL |
| 1 | 12:00am | NULL | 2:00pm |
Reconciled row:
| 1 | 12:00am | 1:00pm | 2:00pm |
An example of an irreconcilable record that I want to detect:
| id | initialize_time | start_time | end_time |
| 1 | 12:00am | NULL | NULL |
| 1 | 12:00am | 1:00pm | NULL |
| 1 | 9:00am | 1:00pm | 2:00pm | -- New initialize time => irreconcilable!
You need dynamic SQL for that, which means you have to create a function or run a DO command. Since you cannot return values directly from the latter, a plpgsql function it is:
CREATE OR REPLACE function f_count_all(_tbl text
, OUT columns text[]
, OUT counts bigint[])
RETURNS record LANGUAGE plpgsql AS
$func$
BEGIN
EXECUTE (
SELECT 'SELECT
ARRAY[' || string_agg('''' || quote_ident(attname) || '''', ', ') || ']
, ARRAY[' || string_agg('count(' || quote_ident(attname) || ')' , ', ') || ']
FROM ' || _tbl
FROM pg_attribute
WHERE attrelid = _tbl::regclass
AND attnum >= 1 -- exclude tableoid & friends (neg. attnum)
AND NOT attisdropped -- exclude deleted columns
GROUP BY attrelid
)
INTO columns, counts;
END
$func$;
Call:
SELECT * FROM f_count_all('myschema.mytable');
Returns:
columns | counts
--------------+--------
{c1, c2, c3} | {17, 1, 0}
More explanation and links about dynamic SQL and EXECUTE in this related question - or a couple more here on SO, try this search.
Related:
Count values for every column in a table
You could even try and return a polymorphic record type to get single columns dynamically, but that's rather complex and advanced. Probably too much effort for your case. More in this related answer.

Concatenate three columns data into one column in Postgres

Can anyone tell me which command is used for concatenate three columns data into one column in PostgreSQL database?
e.g.
If the columns are
begin | Month | Year
12 | 1 | 1988
13 | 3 | 1900
14 | 4 | 2000
15 | 5 | 2012
result like
Begin
12-1-1988
13-3-1900
14-4-2000
15-5-2012
Just use concatenation operator || : http://www.sqlfiddle.com/#!1/d66bb/2
select begin || '-' || month || '-' || year as begin
from t;
Output:
| BEGIN |
-------------
| 12-1-1988 |
| 13-3-1900 |
| 14-4-2000 |
| 15-5-2012 |
If you want to change the begin column itself, begin column must be of string type first, then do this: http://www.sqlfiddle.com/#!1/13210/2
update t set begin = begin || '-' || month || '-' || year ;
Output:
| BEGIN |
-------------
| 12-1-1988 |
| 13-3-1900 |
| 14-4-2000 |
| 15-5-2012 |
UPDATE
About this:
but m not getting null value column date
Use this:
select (begin || '-' || month || '-' || year)::date as begin
from t
Have a look at 9.4. String Functions and Operators
This is an old post, but I just stumbled upon it. Doesn't it make more sense to create a date data type? You can do that using:
select make_date(year, month, begin)
A date seems more useful than a string (and you can even format it however you like using to_char()).