SQL query to return nil for dates not present in the table - sql

I have a table 'my_table'. It has the following data :
ID --- Date
1 --- 01/30/2012
2 --- 01/30/2012
3 --- 05/30/2012
I can write a SQL query to return the count of ID's between certain dates, grouped by month, like this :
{"01/30/2012" => 2, "05/30/2012" => 1}
How can I get a result which has all the missing months between the requested dates with value '0', like this :
{"01/30/2012" => 2, "02/30/2012" => 0, "03/30/2012" => 0, "04/30/2012" => 0, "05/30/2012" => 1}
Thanks in advance.

The way I do it is to have a static table with list of all the dates. In your case that's 30th of each month (what about February?). Lets call this table REF_DATE. It has a single column DT that holds the date.
Assuming that my_table only contains 0 or at most 1 distinct date (30th) in each month, what you need to do is:
select DT,count(ID) from
REF_DT REF
left outer join my_table MT
on REF.DT=my_table.DATE
group by REF.DT;

I came up with somewhat hackish way through rails
class Month<Date # for getting months in range
def succ
self >> 1
end
end
range = Month.new(2010,1,1)..Month.new(2013,1,1) # range of date to query
months=Hash.new
(range).each do |month|
months.merge!({month.to_s => 0}) # get all months as per range requirement of project
end
db_months = MyTable.find_all_by_date(range).group_by{ |u| u.date.beginning_of_month }.map{|m,v| [m.to_s , v.size]} #get all records grouped by months
all_months = months.merge(Hash[db_months]) # merge all missing months
Replace the range with the dates you want also the format of the date as per your requirement.

Related

How can I convert 1 record with a start and end date into multiple records for each day in DolphinDB?

So I have a table with the following columns:
For each record in the above table (e.g., stock A with a ENTRY_DT as 2011.08.22 and REMOVE_DT as 2011.09.03), I’d like to replicate it for each day between the start and end date (excluding weekends). The converted records keep the same value of fields S_INFO_WINDCODE and SW_IND_CODE as the original record.
Table after conversion should look like this:
(only records of stock A are shown)
As the data volume is not large, you can process each record with cj(cross join), then use function unionAll to combine all records into the output table.
The table:
t = table(`A`B`C as S_INFO_WINDCODE, `6112010200`6112010200`6112010200 as SW_IND_CODE, 2011.08.22 1998.11.11 1999.05.27 as ENTRY_DT, 2011.09.03 2010.10.08 2011.09.30 as REMOVE_DT)
Solution:
def f(t, i) {
windCode = t[i][`S_INFO_WINDCODE]
code = t[i][`SW_IND_CODE]
entryDate = t[i][`ENTRY_DT]
removeDate = t[i][`REMOVE_DT]
days = entryDate..removeDate
days = days[weekday(days) between 1:5]
return cj(table(windCode as S_INFO_WINDCODE, code as SW_IND_CODE), table(days as DT))
}
unionAll(each(f{t}, 1..size(t) - 1), false)

Applying advanced filter in Power BI DAX, from a different table

I have the following tables:
Episodes:
Clients:
My DAX calculation sums up [Days_epi] unique values, from Episodes tbl, grouping them by [ProgramID_epi], [EpisodeID_epi], [ClientID_epi].
So, the SUM of [Days_epi] = 3 + 5 + 31 + 8 + 15 + 20 + 10 = 92
Here is my working code for this:
DaysSUM =
CALCULATE (
SUMX (
SUMMARIZE (
'Episodes',
'Episodes'[EpisodeID_epi],
'Episodes'[ProgramID_epi],
'Episodes'[ClientID_epi],
'Episodes'[Days_epi]
),
'Episodes'[Days_epi]
),
FILTER (
'Episodes',
'Episodes'[Category_epi] = "Homeless"
)
)
I need to add two advanced filters to the calculation above:
Filter 1 should ONLY KEEP records in Episodes, if the records in the Clients have the difference between [DischDate_clnt] and [AdmDate_clnt] >= 365.
Filter 1 in SQL statement is
DATEDIFF(DAY, [AdmDate_clnt], [DischDate_clnt]) >= 365)
After that, Filter 2 should ONLY KEEP records in Episodes, if the records in the Clients have
[Date_clnt] >= [AdmDate_clnt] + 12 months. (12 month after the Admission Date)
Filter 2 in SQL statement is
[Date_clnt] <= DATEADD(MONTH, 12, [[AdmDate_clnt])
So, after applying those two filters I expect the records 6 and 10 of the Episodes tbl must be excluded (filtered out), because the records 2 and 3 of the Clients tbl (highlighted in green) are not satisfied my Filter 1 / Filter 2.
Here is the final Episodes dataset I should have (without the 2 records in red):
I was starting to update my DAX code as the following (below).
But keep receiving error "Parameter is not the correct type"
enter
DaysSUM_Filters =
CALCULATE (
SUMX (
SUMMARIZE (
'Episodes',
'Episodes'[EpisodeID_epi],
'Episodes'[ProgramID_epi],
'Episodes'[ClientID_epi],
'Episodes'[Days_epi]
),
'Episodes'[Days_epi]
),
FILTER (
'Episodes',
'Episodes'[Category_epi] = "Homeless"
), TREATAS(DATEDIFF('Clients'[AdmDate_clnt],
'Clients'[DischDate_clnt], DAY)>=365,
'Clients'[Date_clnt])
)
Not exactly sure how to set those 2 filters correctly in DAX Power BI, as I
am relatively new to it.
Please help!
I can't say about all the case. But what is obvious is that you use TREATAS in a wrong way. It works like this TREATAS({"Red", "White", "Blue"}, 'Product'[Color]).
In your case
DATEDIFF('Clients'[AdmDate_clnt],
'Clients'[DischDate_clnt], DAY)>=365
will return TRUE or FALSE value. The first argument of TREATAS - is a column or set of columns not a single value.
You can use the filter like this:
FILTER(
'Clients'
,DATEDIFF(
'Clients'[AdmDate_clnt]
,'Clients'[DischDate_clnt]
,DAY
)>=365
)
This will return you a filtered table.
This may work if your tables are linked.

SQL - How to get rows within a date period that are within another date period?

I have the following table in the DDBB:
On the other side, i have an interface with an start and end filter parameters.
So i want to understand how to query the table to only get the data from the table which period are within the values introduces by the user.
Next I present the 3 scenarios possible. If i need to create one query per each scenario is ok:
Scenario 1:If the users only defines start = 03/01/2021, then the expected output should be rows with id 3,5 and 6.
Scenario 2:if the users only defines end = 03/01/2021, then the expected output shoud be rows with id 1 and 2.
Scenario 3:if the users defines start =03/01/2021 and end=05/01/2021 then the expected output should be rows with id 3 and 5.
Hope that makes sense.
Thanks
I will assume that start_date and end_date here are DateFields [Django-doc], and that you have a dictionary with a 'start' and 'end' as (optional) key, and these map to date object, so a possible dictionary could be:
# scenario 3
from datetime import date
data = {
'start': date(2021, 1, 3),
'end': date(2021, 1, 5)
}
If you do not want to filter on start and/or end, then either the key is not in the dictionary data, or it maps to None.
You can make a filter with:
filtr = {
lu: data[ky]
ky, lu in (('start', 'start_date__gte'), ('end', 'end_date__lte'))
if data.get(ky)
}
result = MyModel.objects.filter(**filtr)
This will then filter the MyModel objects to only retrieve MyModels where the start_date and end_date are within bounds.

LEFT JOIN include data

I have an application which handles school vacation. Unfortunately there are three kinds of different school vacations: Country wide, Federal State wide and City wide vacations. I store all the information in a table days, a table vacation_periods and a connection table slots:
days {
id:integer
date_value:date
}
slots {
id:integer
day_id:integer
vacation_period_id:integer
}
vacation_periods {
id:integer
starts_on:date
ends_on:date
name:string
country_id:integer
federal_state_id:integer
city_id:integer
}
I want to select all days within a specific time frame. Let's say Jan 1st of 2017 to Jan 31st of 2017. I can get those days with:
SELECT * FROM days WHERE date_value >= '2017-01-01' AND
date_value <= '2017-01-31';
But for my vacation calendar I don't just need the days but also the information which vacation_periods are within. Assuming I search for all vacation_periods which are in that time frame and which have
country_id == 1 or federal_state_id == 5 or city_id == 30
I've read about JOINS and LEFT JOINS which seem to be the solution to the problem. But I can't get everything together.
Is it possible to send one SQL request which returns all days within the requested time frame and the additional information if a vacation_period that fits the country_id == 1 or federal_state_id == 5 or city_id == 30 rule is connected via slots to each day. Including the name of that vacation_period?
If one request is not possible: Which is the quickest way to solve this within the database? How many requests? What kind of requests?
If possible I'd like to get a result in some kind of this form:
- date_value: "2017-01-01"
- date_value: "2017-01-02"
- date_value: "2017-01-03"
* vacation_period.id: 15
* vacation_period.name: "foobar"
- date_value: "2017-01-04"
* vacation_period.id: 15
* vacation_period.name: "foobar"
- date_value: "2017-01-05"
* vacation_period.id: 15
* vacation_period.name: "foobar"
- date_value: "2017-01-06"
- date_value: "2017-01-07"
...
The following query might give you the answer you are looking for:
SELECT * FROM days WHERE date_value >= '2017-01-01' AND date_value <='2017-01-31'
INNER JOIN slots ON days.id = slots.day_id
INNER JOIN vacation_periods ON vacation_periods.id = slots.vacation_period_id
I think you can get an unformatted version of what you want (that could be processed into a hierarchical output) with
CREATE TYPE vacation_authority AS ENUM
('COUNTY', 'FED-STATE', 'CITY');
/* not necessary, but cleans up the vacation_period table */
change to let vacation_period have only one id, and a new field authority of type vacation_authority. You can now make a primary key out of either the id field or (id, authority), depending on how the vacation data comes into the system.
SELECT date_value, vp.name, vp.id /* is the ID meaningful or arbitrary? */
FROM dates LEFT JOIN vacation_periods vp
WHERE date_value BETWEEN vp.starts_on AND vp.ends_on; -- inclusive range
Now if there are multiple holidays spanning a given date, this will be multiple records in the output. It's not clear what you want in this case.
None of the other answers was able to solve my problem but they let me to the solution so I'm grateful for them. Here's the solution:
SELECT days.date_value, slots.period_id, vacation_periods.name FROM days
LEFT OUTER JOIN slots ON (days.id = slots.day_id)
LEFT OUTER JOIN vacation_periods ON (slots.period_id = vacation_periods.id)
WHERE days.date_value >= '2017-01-05'
AND days.date_value <='2017-01-15'
AND (vacation_periods.id IS NULL
OR vacation_periods.country_id = 1
OR vacation_periods.federal_state_id = 5)
ORDER BY days.date_value;

LINQ query help please. Selecting most recent record for each FK

Let's say I have a table that looks like this:
Id CheckboxId Selected DateCreated
1 1 1 1/1/2010
2 2 1 1/2/2010
3 1 0 1/3/2010
4 3 1 1/4/2010
5 3 0 1/5/2010
CheckboxId is a FK and the table is just a history of when the boxes are checked or unchecked.
What I want to get is the most recent record for each CheckboxId. In the case of my demo table I want rows 2, 3, and 5. How would you accomplish this? Also I'm sure this is as easy as a "where" at the beginning of the query but if it could also be modified to only get records before a specified date that would be fantastic.
I'm having trouble figuring out how I would write a query to do this in SQL and it's making a link query impossible. I'm sure it has to be a selection from a sub query of distinct checkboxIds coupled with a group by or something but my SQL just isn't that great.
Many thanks for your help.
Should be something like this:
var results = (from x in context
group x by x.CheckboxID into g
select new
{
CheckboxID = g.Key,
MaxItem = g.OrderByDescending(o => o.DateCreated).FirstOrDefault()
});
Then you can do:
foreach (var x in results)
x.MaxItem.Selected //...etc.
Use a subquery to get the most recent entries per CheckBoxId, then join to that table to get the rest of the results:
;with CheckBoxRecent as (
select
CheckBoxId
,max(DateCreated) as MostRecentDate
from
CheckBoxData T
where
T.DateCreated < #SpecifiedDate
group by
CheckBoxId
)
select
T1.*
from
CheckBoxData T1
inner join
CheckBoxRecent T2 on T1.CheckBoxId = T2.CheckBoxId
and T1.DateCreated = T2.MostRecentDate
order by
CheckBoxId
I leave it as an exercise for the reader to convert to LINQ :)
According to your comment you want checkboxes selected on a specified date
var results = db.CheckBoxHistory.Where(cbh => cbh.Selected == 1 && cbh.DateCreated.Date == DateSpecified)
will get you those results, if you want to limit it to the latest by CheckboxId just add this
.GroupBy(cbh => cbh.CheckboxId)
you could loop the results and grab the latest for each checkboxid like so
foreach(var result in results) {
var latest = result.OrderByDescending(cbh => cbh.DateCreated).FirstOrDefault();
//latest has all fields in the checkboxhistory table
}