How do I join to a "fixed vector" in SQL? - sql

By "fixed vector" I mean a static list of values, like 1 through 24.
The current query looks like this (simplified)
SELECT Period, Profit FROM Projections
But the data is "sparse" — so there's not a row for every period.
What query will give me a row for peiods 1-24 every time, with zeros (or NULLs) where there's no data?
I would like to do this with just the query to avoid a mess of client code.
Thanks!

You could make a udf called udfRange(start int,count int) or something like that, and left-join to the output of the function.
Or for something really quick and dirty, you could join to a subselect that looked like
SELECT DATA.Period, P.Profit
FROM (
SELECT 1 AS Period
UNION SELECT 2
...
UNION SELECT 24) AS DATA
LEFT JOIN Projections P ON DATA.Period = P.Period

Why not create a 'Periods' lookup table, with values 1 - 24 (and any other columns that might be relevant, like a description of the period, or its name) then do a left outer join between the Periods lookup table and your projections table.

Related

Add a where condition in one subquery referencing a table in another subquery (ANSI SQL)

In subquery 'two' I want to add a where condition which is based on a column in subquery 'one', that is, I want to add WHERE one."Call Type" = 'Demo' within my second subquery but that gives me an alias error. Basically, in 'two' I only want the count of those rows which have had a call type = demo as given in table 'one' (Final objective is to find the ratio of the two counts mentioned in the code). Any suggestions on how this can be achieved?
SELECT
COALESCE(one.Period, two.Period) AS Period,
one.TotalDemos,
two.TotalTrials,
Round(100.0 * one.TotalDemos / two.TotalTrials, 2) AS percentage
FROM ( SELECT
"Call Date" AS Period,
COUNT(*) AS TotalDemos
FROM "customer_calls"
WHERE "Call Type" = 'Demo'
GROUP BY Period
) AS one
FULL OUTER JOIN( SELECT
"modified" AS Period,
COUNT(*) AS TotalTrials
FROM "users"
WHERE "customertype" = 0
GROUP BY Period
) AS two ON one.Period = two.Period
Edit - My period values are as datestamps (date - time) whereas I'd want the aggregation or ratio/percentage by month of year instead of day. Not sure how that can be done using coalesce here. Any help on this would also be great.
Based on the table definitions that you've provided, you can achieve what you're after with Common Table Expressions (CTE). Example provided with the query below.
However, wee warning, trying to determine users that have made a demo call by just the Period is not recommended. If my assumption that Period is a date / time duration, then it is very likely that your query will not achieve what you want it to (i.e. you'll have records from the query that will not be a demo call). To get the query precise, you'll have to determine what the actual table joins between customer_calls and users are for your query to be effective.
Also, another wee warning, I generally don't recommend using FULL OUTER JOIN as it will return every record from both tables, meaning that you'll have a lot of records there that you don't want (i.e. lines in one that don't join to two and vice versa). INNER JOIN should suffice assuming you know the database / table structures well.
;WITH [one] AS (
SELECT
"Call Date" AS Period,
COUNT(*) AS TotalDemos
FROM "customer_calls"
WHERE "Call Type" = 'Demo'
GROUP BY Period
), [two] AS (
SELECT
"modified" AS Period,
COUNT(*) AS TotalTrials
FROM "users"
WHERE "customertype" = 0
AND Period IN (SELECT Period FROM [one])
GROUP BY Period
)
SELECT
COALESCE(one.Period, two.Period) AS Period,
one.TotalDemos,
two.TotalTrials,
Round(100.0 * one.TotalDemos / two.TotalTrials, 2) AS percentage
FROM one
FULL OUTER JOIN two
ON one.Period = two.period

SQL to get different values into 1 row

I have the following table structure:
VEH_GRP VEH_CODE_IND CATEGORY DATE Mileage_1 Mileage_2
1 A CAR 31-May-08 10
1 B CAR 31-May-08 100
How can I use a sql query to combine them into 1 row? Ideally I would want to perform computation to divide Mileage_1 over Mileage_2..
Thanks everyone.
You would need to use a self join to combine two rows based on some criteria like which 2 rows you require to be combined.
Example :
select
t1.*,t2.* ,t1.mileage_1/t2.mileage_2
from
data_table t1
inner join
data_table t2
on
t1.veh_grp = t2.veh_grp
Also, you'll need to think of some logic to select which row should represent t1 and which should represent t2.
You can use aggregation. I'm not quite sure what the results would look like but:
select VEH_GRP, CATEGORY, DATE,
SUM(Mileage_1), SUM(Mileage_2),
SUM(Mileage_1) / SUM(Mileage_2)
from t
group by VEH_GRP, CATEGORY, DATE;

Select the max value on a multiple table join

I am trying to get the maximum date out of multiple tables when those table have a particular geometry.
My tables more or less look like that (of course they're all different but I shortened them in order to make it clearer ):
A table type :
Id, Info, Geometry, Date
And finally I have an other table that looks like that (shortened again) :
B table:
Id, Geometry
Now, what I want to do is to join all my A type tables on Geometry where they intersect with the B table Geometry, and to get the A table that has the most recent date.
I currently have the following request which is working:
UPDATE last_updateT SET date_last_update= S.dateMax
FROM
(SELECT B.gid, MAX(A.last_date) AS dateMax
FROM B
JOIN A ON ST_Intersects(B.geometry, A.geometry)
GROUP BY B.gid) S
WHERE T.id = S.gid;
Now I'd like to be able to do that kind of join on multiple table that looks like table A. I've heard of the function GREATEST but I am not sure about how to use it.
Also, I use Postgresql if that makes any differences.
It seems you are looking for UNION ALL, so you can treat the data from different tables as if it were data from only one table:
SELECT
b.gid,
MAX(x.last_date) AS dateMax
FROM b
JOIN
(
SELECT geometry, last_date FROM a
UNION ALL
SELECT geometry, last_date FROM aa
UNION ALL
SELECT geometry, last_date FROM aaa
) x ON ST_Intersects(b.geometry, x.geometry)
GROUP BY b.gid;
In broad strokes, MAX is an aggregate function, so you use MAX to get the highest value from the same column over a number of different rows.
GREATEST is a scalar function, you use GREATEST to get the highest value from different columns in the same row.
eg:
SELECT GREATEST(col1,col2,col3)
Greatest: https://www.postgresql.org/docs/9.5/static/functions-conditional.html
Max: https://www.postgresql.org/docs/9.5/static/functions-aggregate.html

Complex sql query involving timestamp to timestamp periods and joins and sums - is it even possible?

I am trying to create database query, which will select rows from one table, create periods from those rows (using Lag window function), and join the query with rows from different table, where it sums value(s)from one column per row in first table.
Table A:
id,
created_at,
object_id
Table B:
id,
end_time,
value,
object_id
And rows, that query yields should consist of columns something like:
lag(tablea.created_at) over(tablea.object_id, tablea.created_at),
tablea.created_at,
tablea.object_id
sum(tableb.value) where it sums the tableb.value from matching period
I tried creating query where i put the window function into WHERE clause only to get an error. I also tried puting the period into join on clause but that also raised an error.
It is no problem, if it is not possible. I just want to know if it possible and in that case how it is possible. If it is not possible, then i just will try to come up with alternative aproach.
Edit: link to example sqlfiddle: http://sqlfiddle.com/#!1/c7878
Edit2: The SQL i tried was something like:
SELECT lag(a.created_at, a.created_at, a.object_id, sum(b.value) from tablea a left join tableb b on (something) order by a.object_id, a.created_at
But obviously that did not work, because i could not use window function in ON clause. That's where i got stuck

Combining the results of two SQL queries as separate columns

I have two queries which return separate result sets, and the queries are returning the correct output.
How can I combine these two queries into one so that I can get one single result set with each result in a separate column?
Query 1:
SELECT SUM(Fdays) AS fDaysSum From tblFieldDays WHERE tblFieldDays.NameCode=35 AND tblFieldDays.WeekEnding=?
Query 2:
SELECT SUM(CHdays) AS hrsSum From tblChargeHours WHERE tblChargeHours.NameCode=35 AND tblChargeHours.WeekEnding=?
Thanks.
You can aliasing both query and Selecting them in the select query
http://sqlfiddle.com/#!2/ca27b/1
SELECT x.a, y.b FROM (SELECT * from a) as x, (SELECT * FROM b) as y
You can use a CROSS JOIN:
SELECT *
FROM ( SELECT SUM(Fdays) AS fDaysSum
FROM tblFieldDays
WHERE tblFieldDays.NameCode=35
AND tblFieldDays.WeekEnding=1) A -- use you real query here
CROSS JOIN (SELECT SUM(CHdays) AS hrsSum
FROM tblChargeHours
WHERE tblChargeHours.NameCode=35
AND tblChargeHours.WeekEnding=1) B -- use you real query here
You could also use a CTE to grab groups of information you want and join them together, if you wanted them in the same row. Example, depending on which SQL syntax you use, here:
WITH group1 AS (
SELECT testA
FROM tableA
),
group2 AS (
SELECT testB
FROM tableB
)
SELECT *
FROM group1
JOIN group2 ON group1.testA = group2.testB --your choice of join
;
You decide what kind of JOIN you want based on the data you are pulling, and make sure to have the same fields in the groups you are getting information from in order to put it all into a single row. If you have multiple columns, make sure to name them all properly so you know which is which. Also, for performance sake, CTE's are the way to go, instead of inline SELECT's and such. Hope this helps.
how to club the 4 query's as a single query
show below query
total number of cases pending + 2.cases filed during this month ( base on sysdate) + total number of cases (1+2) + no. cases disposed where nse= disposed + no. of cases pending (other than nse <> disposed)
nsc = nature of case
report is taken on 06th of every month
( monthly report will be counted from 05th previous month to 05th present of present month)