SQL - How to returns values outside a date range query - sql

Hoping someone can help out here, I have the following data
Field 1 Field 2 Date Data
1 1 12/09/14 1
2 2 12/09/14 1
3 1 11/09/14 1
4 3 11/09/14 1
I need to write an sql query that sums all "Data" based on a date range and then anything that matches in Field 2. So if a line is out of the date range but the value in Field 2 matches another line that is within the date range, it should be included
For example, if I was to query everything for the 12/09/14, I want to see the sum of line 1, 2 and 3.... as line 3 is outside of the date range but it matches line 1 in the "Field 2" column. Line 4 should not be included as it is outside the range and does not have a matching value in "Field 2"
Any ideas?
I've been playing around with variations of queries but it either selects only the date range values or everything :(
EDIT:
Ok I've given Rajesh answer a try and it doesn't seem to include the data outside the date range. I was expecting the final sum in this example to equal 3 but it's only showing 2
select sum(a) from (
select sum(batch_m2_nett) as a
from batch_inf
where batch_date = to_date('30/09/15','DD/MM/RR')
union
select sum(f2.batch_m2_nett) as a
from batch_inf f1
inner join batch_inf f2
on f1.batch_date = to_date('30/09/15','DD/MM/RR')
and f1.batch_opt_start_batch = f2.batch_opt_start_batch
and f2.batch_date != to_date('30/09/15','DD/MM/RR')
);
SUM(A)
------
2
SQL> select batch_no, batch_opt_start_batch, batch_date, batch_m2_nett from batch_inf where batch_no in (8811,8812,8814);
BATCH_NO BATCH_OPT_START_BATCH BATCH_DATE BATCH_M2_NETT
-------- --------------------- --------------- -------------
8811 8814 30-SEP-15 1
8812 8814 30-SEP-15 1
8814 8814 01-OCT-15 1

the first statement gets sum of data values where date matches
the second statement gets sum of data values where field2 of matched date row is matching with other rows using self join
select SUM(s)
from
(
select SUM(data) as s
from fields
where date ='12/09/14'
union
select sum(f2.data) as s
from fields f1
inner join fields f2
on f1.date ='12/09/14'
and f1.field2 = f2.field2
and f2.date != '12/09/14'
) T

Related

Return 0 in Sheets Query if there is no data

I need some advice in google query language.
I want to count rows depending on date and a condition. But if the condition is not met, it should return 0.
What I'm trying to achieve:
Date Starts
05.09.2018 0
06.09.2018 3
07.09.2018 0
What I get:
Date Starts
06.09.2018 3
The query looks like =Query(Test!$A2:P; "select P, count(B) where (B contains 'starts') group by P label count(B) 'Starts'")
P contains ascending datevalues and B an event (like start in this case).
How can I force output a 0 for the dates with no entry containing "start"?
The main point is to get all needed data in one table in ascending order. But this is only working, if every day has an entry. If there is no entry for a day, the results for "start" do not match the datevalue in column A. 3 in column D would be in the first row of the table then.
I need it like this:
A B C D
Date Logins Sessions Starts
05.09.2018 1 2 0
06.09.2018 3 4 3
07.09.2018 4 5 0
Maybe this is easy to fix, but I don't see it.
Thanks in advance!
You can do some pre-processing before the query. Ex: check if column B contains 'start' with regexmatch and use a double unary (--) to force the boolean values into 1's and 0's. The use query to sum.
=Query(Arrayformula({--regexmatch(Test!$B2:B; "start")\ Test!$A2:P}); "select Col17, sum(Col1) where Col17 is not null group by Col17 label sum(Col1) 'Starts'")
Change ranges to suit.

SQL: Checking if a number within range of multiple ranges

Lets say we have 2 tables.
Table Values
Id Group Value
--------------------
A X 15
B Y 55
Table Ranges
Group LowLimit HighLimit
--------------------------------
X 0 10
X 20 30
Y 30 40
Y 50 60
I would like to check which Values.Id has value that falls outside the LowLimit and HighLimit of the group it belongs to in Ranges (notice each group has multiple ranges).
The desired result would be
Table Result
Id
--------------
A (because the value 15 is outside the range of both (0..10) and (20..30)
while B is not part of the result because it is within the range of (50..60) even though it is outside the range of (30..40))
What would the sql would be like?
One option uses an exists query:
SELECT
v.ID
FROM [Values] v
WHERE NOT EXISTS (SELECT 1 FROM [Ranges] r
WHERE v.[Group] = r.[Group] AND
v.[Value] BETWEEN r.[LowLimit] AND r.[HighLimit]);
Demo
In plain English, this will check each ID row from Values and check it there does not exist even one range which contains the value. If no such range exists, then this non matching ID would be reported.

capture non occured data from dynamic input data

I have data rules like given below
1|Group1|Mandatory|1st occurrence
2|Group1|Optional|1st occurrence
3|Group1|Mandatory|1st occurrence
1|Group1|Mandatory|2nd occurrence
2|Group1|Optional|2nd occurrence
3|Group1|Mandatory|2nd occurrence
4|Group2|Mandatory|1st occurrence
5|Group2|Mandatory|1st occurrence
6|Group2|Optional|1st occurrence
Here as you can see Group 1 is present two times for data record 1, 2 and 3. It means group 1 can appear min 1 time and max two times. And also can see the occurrence of that specific record under group 1 when it occurs. Mandatory should occur always and optional is may or may not be occur in input data. But all needs to be captured ..what's missing
And here is my input column data. That's a only column am having in input data
1
2
3
1
2
4
5
Is there any way I could get result to identify which data set if missing according to data rules table from input data ? Like in this example, output should like saying Mandatory record(3) is missing from Group 1 in second occurrence. That's only available information would be coming from input data and data rules table.
If any things needs to be added to get desired result...I would like to hear..what it is. All suggestions are welcome.
Thanks
I think You need something like this:
with input as (select column_value id,
count(1) over (partition by column_value order by null
rows between unbounded preceding and current row) cnt
from table(sys.odcinumberlist(1, 2, 3, 1, 2, 4, 5)))
select *
from data
where status = 'Mandatory'
and (id, occurence) not in (select id, cnt from input)
demo
ID GRP STATUS OCCURENCE
---- ---------- ---------- ---------
3 Group1 Mandatory 2
Count how many times id appears in input data and compare result with mandatory occurences in your data.
Edit: explanation
select column_value id,
count(1) over (partition by column_value order by null
rows between unbounded preceding and current row) cnt
from table(sys.odcinumberlist(1, 2, 3, 1, 2, 4, 5))
This part simulates you input data. table(sys.odcinumberlist(1, 2, 3, 1, 2, 4, 5)) is just simulation of inputs, probably these ids are in some table, select them from there. For each provided id I'm counting it's growing number of occurences using function count() in analytic version, so we have this:
id cnt
--- ---
1 1
1 2
2 1
2 2
3 1
4 1
5 1
Next these pairs are compared with mandatory pairs (id, occurence) in your data. If something is missing last select displays this row with a clause not in.
This is how I understood Your question, perhaps You'll need some modifications, but now You have some hints. Hope this helps (and sorry for my bad English ;-) ).

Oracle - SQL Query to return a value from a column in another table where value equals a different column

From within the results of a query I need to take the first 3 digits (got this part - substr) from a column in one table and pull the value from a second table where the 3 digit code is in a different column of the same row. While I'm not looking for assistance in this part I will be grouping by the code column for reference
Example
Table 1 Table 2
3_Digit Code_Column Description
123456 123 Blue
103456 103 Green
so if my substr query return 123 5 times I'm looking for
Blue 3
select t2.Code_Column, count(*)
from table1 t1
join table2 t2
on substr(t1.digit, 0, 3) = t2.Code_Column
group by t2.Code_Column
SQL Fiddle sample

SQL complex grouping "in column"

I have a table with 3 columns (sorted by the first two):
letter
number (sorted for each letter)
difference between current number and previous number of the same letter
I'd like to calculate (with vanlla SQL) a fourth new column RESULT to group these data when the third column (difference of number between contiguos record; i.e #2 --> 4 = 5-1) is greater than 30 marking all the records of this interval with letter-number of the first record (i.e A1 for #1,#2,#3).
Since the difference between contiguos numbers makes sense just for records with the same letter, for the first record of a new letter, the value of differnce is 31 (meaning that it's a new group; i.e. #6).
Here is what I'd like to get as result:
# Letter Number Difference RESULT (new column)
1 A 1 1 A1
2 A 5 4 A1
3 A 7 2 A1
4 A 40 33 A40 (*)
5 A 43 3 A40
6 B 1 31 B1 (*)
7 B 25 24 B1
8 B 27 2 B1
9 B 70 43 B70 (*)
10 B 75 5 B70
Now I can only find the "breaking values" (*) with this query where they get a value of 1:
select letter
,number
,cast(difference/30 as int) break
from table
where cast(difference/30 as int) = 1
Even though I'm able to find these breaking values I can't finish my task.
Can anyone help me finding a way to obtain the column RESULT?
Thanks in advance
FF
As I understand you need to construct the last result column. You can use concat to do that:
SELECT letter
,number
,concat(letter, cast(difference/30 as int)) result
FROM table
HAVING result = 'A1'
after some exercise and a little help from a friend of mine, I've found a possible solution to my sql prolblem.
The only requirment for the solution is that my first record must have a value of 31 in Difference field (since I need "breaks" when Difference > 30 than the previous record).
Here is the query to get the column RESULT I needed:
select alls.letter
,alls.number
,ints.letter||ints.number as result
from competition.lag alls
,(select letter
,number
,difference
,result
from (select letter
,number
,difference
,case when difference>30 then 1 else 2 end as result
from competition.lag
) temp
where result = 1
) ints
where ints.letter=alls.letter
and alls.number>=ints.number
and alls.number-30<=ints.number