SQL Updated question conditional division - sql

Given columns A and B from Table1:
A B
Small 3
Med 4
Med 1
Large 2
Small 1
Given columns S, M, L from Table2:
S M L
5 5 3
8 2 1
4 6 5
2 2 8
I want to create a new column in Table1 that outputs the quotients of values of column B and Avg(Table2.S) only if the entry in the same row in column A of is 'Small'. If column A has 'Med', we divide by Avg(Table2.M) and if it has 'Large', we divide by Avg(Table2.L). It would continue to check this row by row. For example, in the first row of column B, we have '3', and on the same row in column A, we have 'Small', so we would output 0.6316 (3/Avg(Table2.S)). So the expected column, let's call it C, would be:
C
0.6316
1.0667
0.2667
0.4076
0.2105
How would I output C using MS Access SQL? I tried
Select
Switch(Table1.A ='Small', Table1.B/Avg(Table2.S),
Table1.A ='Med', Table1.B/Avg(Table2.M),
Table1.A ='Large', Table1.B/Avg(Table2.L))
From Table1, Table2
but I usually get an error that says my query doesn't include the specified expression as an aggregate function.

Here is a way to do this
select A,B,switch(A="Small",x.avg_s,A="Med",avg_m,A="Large",avg_l) as avg_vals,B/switch(A="Small",x.avg_s,A="Med",avg_m,A="Large",avg_l)
from table1 y,
(select avg(S) as avg_s,avg(M) as avg_m,avg(L) as avg_l
from table2
)x
The output is

Related

SQL - store count in same column based on different values in multiple column

I have a table (TableA) which contains three columns
Sample rows given below
ID
METRIC
TYPE
X
A
J
X
A
J
X
A
K
X
B
K
Y
A
J
Y
B
J
Y
B
L
In the output I need one column for count of rows and distinct count of ids based on the following criteria:
Count all rows of input data as TBL_TOT, count distinct IDs from the input table
For each value of column Metric, count the total records and count the distinct IDs.
For each value of column Type, count the total records and count the distinct IDs.
Output will look like this:
VALUE
COUNT
DISTINCT_ID
TBL_TOT
7
2
A
4
2
B
3
2
J
4
2
K
2
1
L
1
1
Currently I am doing a Union all for all different cases like below:
SELECT 'TBL_TOT',COUNT(*) AS COUNT,COUNT(DISTINCT ID) AS DISTINCT_OUNT
FROM TABLEA
UNION ALL
SELECT METRIC,COUNT(*) AS COUNT,COUNT(DISTINCT ID) AS DISTINCT_OUNT
FROM TABLEA
GROUP BY METRIC
UNION ALL
SELECT TYPE,COUNT(*) AS COUNT,COUNT(DISTINCT ID) AS DISTINCT_OUNT
FROM TABLEA
GROUP BY TYPE
;
Is there any other efficient way of getting this result other than UNION ALL and PIVOT/UNPIVOT?
If not, then if we ignore the tbl_tot part, can the bottom two unions be done in some other way?
The actual dataset is huge and query execution is taking too long.

How to take MAX from column values in SparkSQL

I have a use case where I need to take max value from different columns from a table in sparksql.
Below is a sample table -
I want to take the max of values from columns a, b and c without using the union clause.
Below is the SL query I executed -
SELECT (
SELECT MAX(myval)
FROM (VALUES (a),(b),(c)) AS temp(myval)
) AS MaxOfColumns
FROM
table
But this is throwing an error - "cannot evaluate expression outer() in inline table definition; line 3 pos 16"
Could you please help me with this?
array_max
with t(id,a,b,c) as (select stack(2 ,100,1,2,3 ,200,5,6,4))
select *, array_max(array(a,b,c)) as MaxOfColumns
from t
id
a
b
c
MaxOfColumns
100
1
2
3
3
200
5
6
4
6

Finding a pair of row in SQL

I am very confused how to define the problem statement but Let's say below is table History i want to find those rows which have a pair.
Pair I will defined like column a and b will have same value and c should have False and d should be different for both row.
If I am using Java i would have set row 3, C column as true when i hit a pair or would have saved both row 1 and row 3 into different list. So that row 2 can be excluded. But i don't know how to do the same functionality in SQL.
Table - History
col a, b, c(Boolean ), d
1 bb F d
1 bb F d
1 bb F c
Query ? ----
Result - rows 1 and 3.
Assuming the table is called test:
SELECT
*
FROM
test
WHERE id IN (
SELECT
MIN(id)
FROM
test
WHERE
!c
AND a = b
AND d != a
GROUP BY a, d
)
We get the smallest id of every where matching your conditions. Furthermore we group the results by a, d which means we get only unique pairs of "a and d". Then we use this ids to select the rows we want.
Working example.
Update: without existing id
# add PK afterwards
ALTER TABLE test ADD COLUMN id INT PRIMARY KEY AUTO_INCREMENT FIRST;
Working example.
All the rows match the conditioin you specified. A "pair" happens when:
column a and b will have same value, and
c should have False, and
d should be different for both rows.
1 and 3 will match that as well as 2 and 3. Also, 3 and 1 will match as well as 3 and 2. There are four solutions.
You don't say which database, so I'll assume PostgreSQL. The query that can search using your criteria is:
select *
from t x
where exists (
select null from t y
where y.a = x.a
and y.b = x.b
and not y.c
and y.d <> x.d
);
Result:
a b c d
-- --- ------ -
1 bb false d
1 bb false d
1 bb false c
That is... the whole table.
See running example at DB Fiddle.

ladder-like record selection without looping

I have a table like this, A and B as columns:
A B
1 0
2 1
3 2
4 3
A record can be selected by defining a value for A. If the selected row has a value for B, the row whose A's value is equal to the record's B must also be selected, and if that selected record has a B it must again be selected and so on.
Example:
If the user queries for A = 3, the returned rows must be:
A B
3 2
2 1
1 0
This is the output because of this condition: A3 has a value for B; there is a record whose A is equal to the first row's B which is 2 and the second record's B is 1 which still has a matching record.
Is there a way this can be done without looping through the records?
You can use recursive CTE to achieve this:
http://msdn.microsoft.com/en-us/library/ms186243(v=sql.105).aspx
;WITH RCTE AS
(
SELECT * FROM Table1 WHERE A = 3
UNION ALL
SELECT t.* FROM RCTE r
INNER JOIN Table1 t ON r.B = t.A
)
SELECT * FROM RCTE
SQLFiddle DEMO

Select a row from the group of row on a particular column value

I want to write a query to achieve the following. I have a table xyz in which there are multiple row with same column value(1) in say column a.
I want to find in column b doesn't have a particular value for the set of rows with value 1 in column a.
Table xyz
---------
a b
1 te
1 we
1 re
2 te
2 re
3 ge
4 re
So basically I want to find if the column b does not have the value 'te' for a set of values from column a
when i do
Select a from xyz where b <> 'te'
group by a
I will get 1,2,3 and 4 both for the result.
But I want the result should only contain 1 and 2. Please help.
Select a from xyz where (b<>'te') and ((a=1) or (a=2))
or as variant
select a from xyz where (b<>'te') and (a in (1, 2))
select a from xyz
where b! = 'tz' and
a in (select a from xyz where b = 'tz')
Is this what you are looking for?
Try this for you:
Select a from xyz where b = 'te'
group by a
I just realized I didn't and still don't understand what you are asking. Could you try and restate it? The only non-trivial interpretation I can come up with that would return 1 and 2 based on this data would be:
What are the values of a such that there is a row with both a and
'te' and a row with both a and a value other than 'te'
in which case a query would be:
SELECT DISTINCT q1.a FROM (SELECT a FROM xyz WHERE b='te') q1
JOIN (SELECT a FROM xyz WHERE b!='te') q2 ON
q1.a=q2.a
The interpretation which corresponds with returning 3 and 4 in your example or with returning 1 and 2 in your geo example would be:
What are the values of a for which a te row does not exist?
in which case a query would be:
SELECT DISTINCT a FROM xyz WHERE a NOT IN (SELECT a FROM xyx WHERE b='te')
as shown here (sqlfiddle is acting up, so I used ideone)