I'm trying to write a query that will select rows from a table but I'm struggling a little with there WHERE clause.
I have a list of C# objects that has an ID and a Date. I want to find rows in my database where the ID is equal to one of the ids in my list of objects, but at the same time, the Date that comes with the specific ID has to be between a ValidFrom and a ValidTo field in the Database.
I already a query that will work but it is not a very pretty solution:
SELECT *
FROM [dbo].[Employees] AS emp
WHERE emp.IsDeleted = 0
AND (emp.EmployeeId = 1
AND (emp.ValidFrom <= '2017-05-01')
AND (emp.ValidTo > '2017-05-01'))
OR (emp.EmployeeId = 2
AND (emp.ValidFrom <= '2018-05-01')
AND (emp.ValidTo > '2018-05-01'))
And then I'd proceed to add the 'OR' statement from there.
Is there a more optimal way for me to accomplish this?
You can populate the filtering criteria in a separate table:
CREATE TABLE #RecordsTobeFiltered
(
EmployeeId INT
,ValidFrom DATE
,ValidTo DATE
);
INSERT INTO #RecordsTobeFiltered (EmployeeId, ValidFrom, ValidTo)
VALUES (1, '2017-05-01', '2017-05-01')
,(2, '2018-05-01', '2018-05-01')
--- and many records as you need
SELECT *
FROM [dbo].[Employees] AS emp
INNER JOIN #RecordsTobeFiltered F
ON emp.EmployeeId = f.EmployeeId
and emp.ValidFrom <= f.ValidFrom
and emp.validTo > f.ValidTo
WHERE emp.IsDeleted = 0;
Related
I have a table named MarketData, and I am trying to pull certain columns from MarketData and insert them to another table called Payups. But I only want to insert data that doesn't repeat onto Payups.
Keep in mind, the MarketData table includes more columns that I don't need in the PayUps column.
After I execute the query below, it keeps on adding records that are similar.
INSERT INTO [MortgagePipeline].[dbo].[PayUps]
(
RecordDate
,Investor
,Product
,MinCoupon
,[Payup(bcp)]
)
SELECT DISTINCT t1.ContractDate
,t1.SourceCode
,t1.ProductName
,t1.ContractInterestRate
,t1.ContractPrice
FROM [MortgagePipeline].[dbo].[MarketData] t1
WHERE NOT EXISTS
(
SELECT RecordDate
,Investor
,Product
,MinCoupon
,[Payup(bcp)]
FROM [MortgagePipeline].[dbo].[PayUps] t2
WHERE t2.RecordDate = t1.ContractDate
AND t2.Investor = t1.SourceCode
AND t2.Product = t1.ProductName
AND t2.MinCoupon = t1.ContractInterestRate
AND t2.[Payup(bcp)] = t1.ContractPrice
AND t2.MaxCoupon = NULL
AND t2.PayupName = NULL
)
RecordDate, Investor , Product ,MinCoupon ,[Payup(bcp)], MaxCoupon PayupName are all the columns that exists on Payups. all of The values of those columns are inserted from the MarketData Table except from MaxCoupon and PayupName that remain null.
I have investigated lots of posts relating to SQL merging of two tables, and am very familiar with merging in SQL, but this one has me stumped. Here is the scenario: I have a table of values which are stored by Grade and Currency, i.e.
GradeID = 3, Rate = 175, CurrencyID = 5.
There are five grades, a different value for each and these are the default values for each grade in GBP (CurrencyID = 5).
I have another table with an extra column of Fiscal Period, which is a 1st of the month date to which the rate applies, i.e.
GradeID = 3, Rate = 150, FiscalPeriodID = 95, CurrencyID = 5.
Not all values for each grade, fiscal period and currency will be different from the default, so users will only enter differences where necessary. I have a Windows form for the user to view and update these values, but am struggling to show the results of both tables together.
The ideal solution for a case where there is no stored data, i.e. only the default values apply, is that the screen will show the default values at the current fiscal period i.e. 95 = 01/11/2017, but where there are values which have been entered, the table will show the changed rows by grade but grouped by each fiscal period which has a non-default value.
The first part of setting the current fiscal period for the default values is relatively easy:
SELECT [RateID], [GradeID], [ChargeRate],
(SELECT [FiscalPeriodID] FROM [dbo].[FiscalPeriod] WHERE MONTH([FiscalPeriod]) =
MONTH(GETDATE()) AND YEAR([FiscalPeriod]) = YEAR(GETDATE())) AS [FiscalPeriodID]
,[CurrencyID]
FROM [dbo].[DefaultChargeRateByLevel]
But what I'd like to do is perform one query that does either this simple selection (when no results returned for any fiscal period) or a merge of the default and updated values to show groups of 5 values per fiscal period.
My initial thought was to populate two temporary tables with the results from each query then perform a merge, but I can't figure out how to populate the fiscal period for each 'group of values. This is what i have so far, but it fails with the following error: Cannot insert the value NULL into column 'FiscalPeriodID', table 'tempdb.dbo.#TempTarget
IF OBJECT_ID('tempdb..#TempTarget') IS NOT NULL
DROP TABLE #TempTarget
IF OBJECT_ID('tempdb..#TempSource') IS NOT NULL
DROP TABLE #TempSource
SELECT
[GradeID]
,[ChargeRate]
,[FiscalPeriodID]
,[CurrencyID]
INTO #TempTarget
FROM (SELECT
[GradeID]
,[ChargeRate]
,[FiscalPeriodID]
,[CurrencyID]
FROM
[dbo].[ChargeRateByProjectAndLevel]) AS A
SELECT * FROM #TempTarget
SELECT
[GradeID]
,[ChargeRate]
,[FiscalPeriodID]
,[CurrencyID]
INTO #TempSource
FROM (SELECT
D.[GradeID]
,D.[ChargeRate]
,M.[FiscalPeriodID]
,D.[CurrencyID]
FROM
[dbo].[DefaultChargeRateByLevel] AS D
LEFT JOIN #TempTarget AS M ON M.[GradeID] = D.[GradeID]
AND M.[CurrencyID] = D.[CurrencyID]
) AS B
SELECT * FROM #TempSource
/* Now merge rates data from temp table to FxRates table */
MERGE #TempTarget AS [Target]
USING #TempSource AS [Source]
ON [Source].[GradeID] = [Target].[GradeID]
AND [Source].[CurrencyID] = [Target].[CurrencyID]
WHEN NOT MATCHED BY TARGET THEN
INSERT (
[GradeID]
,[ChargeRate]
,[FiscalPeriodID]
,[CurrencyID]
)
VALUES (
[Source].[GradeID]
,[Source].[ChargeRate]
,[Source].[FiscalPeriodID]
,[Source].[CurrencyID]
);
SELECT * FROM #TempTarget
I have a table variable #WEEKS_MONTH like this:
I must update this table (column SUMMARY) with query:
SELECT SUM(AVAI_NUM)
FROM SCAVAI
WHERE AVAI_DST >= (SELECT WEEKSTART
FROM #WEEKS_MONTH
WHERE WEEKOFMONTH = 1)
AND AVAI_DST <= (SELECT WEEKEND
FROM #WEEKS_MONTH
WHERE WEEKOFMONTH = 1)
Problem that I have is that I don't know how to connect that table with this query. (WEEKOFMONTH must be from table, row by row. For example I've just put number 1.)
Just use a subquery in an UPDATE:
UPDATE wm
SET Summary = (SELECT SUM(s.AVAI_NUM)
FROM SCAVAI s
WHERE s.AVAI_DST BETWEEN wm.WEEK_START and wm.WEEK_END)
FROM #WEEKS_MONTH wm
Here's my data;
table A.pickup_date is a date column
table A.biz_days is the business days I want to add up to A.pickup_date
table B.date
table B.is_weekend (Y or N)
table B. is_holiday (Y or N)
Basically from table B, I know for each date, if any date is a business day or not. Now I want to have a third column in table A for the exact date after I add A.business_days to A.pickup_date.
Can anyone provide me with either a case when statement or procedure statement for this? Unfortunately we are not allowed to write our own functions in Teradata.
This is pretty darned ugly, but I think it should get you started.
First I created a volatile table to represent your table a:
CREATE VOLATILE TABLE vt_pickup AS
(SELECT CURRENT_DATE AS pickup_date,
8 AS Biz_Days) WITH DATA PRIMARY INDEX(pickup_date)
ON COMMIT PRESERVE ROWS;
INSERT INTO vt_pickup VALUES ('2015-02-24',5);
Then I joined that with sys_calendar.calendar to get the days of the week:
CREATE VOLATILE TABLE VT_Days AS
(
SELECT
p.pickup_date,
day_of_week
FROM
vt_pickup p
INNER JOIN sys_calendar.CALENDAR c
ON c.calendar_date >= p.pickup_date
AND c.calendar_date < (p.pickup_date + Biz_Days)
) WITH DATA
PRIMARY INDEX(pickup_date)
ON COMMIT PRESERVE ROWS
Then I can use all that to generate the actual delivery date:
SELECT
p.pickup_date,
p.biz_days,
biz_days + COUNT(sundays.day_of_week) + COUNT (saturdays.day_of_week) AS TotalDays,
COUNT (sundays.day_of_week) AS Suns,
COUNT (saturdays.day_of_week) AS Sats,
p.pickup_date + totaldays AS Delivery_Date,
FROM
vt_pickup p
LEFT JOIN vt_days AS Sundays ON
p.pickup_date = sundays.pickup_date
AND sundays.day_of_week = 1
LEFT JOIN vt_days AS saturdays ON
p.pickup_date = saturdays.pickup_date
AND saturdays.day_of_week = 7
GROUP BY 1,2
You should be able to use the logic with another alias for your holidays.
The easiest way to do this is calculating a sequential number of business days (add it as a new column to your calendar table if it's a recurring operation, otherwise using WITH):
SUM(CASE WHEN is_weekend = 'Y' OR is_holiday = 'Y' THEN 0 ELSE 1 END)
OVER (ORDER BY calendar_date
ROWS UNBOUNDED PRECEDING) AS biz_day#
Then you need two joins:
SELECT ..., c2.calendar_date
FROM tableA AS a
JOIN tableB AS c1
ON a.pickup_date = c1.calendar_date
JOIN tableB AS c2
ON c2.biz_day# = c1.biz_day# + a.biz_days
AND is_weekend = 'N'
AND is_holiday = 'N'
I am trying to write a Business Object report to show a list of the people who have not returned a timesheet on a selected date, but I can't figure out how to stop the SQL query returning multiple entries for individuals.
My Staff_Table contains 2 columns - Employee No & Name
My Timesheet_Table contains, among other things, Employee No & Week_Ending_Date.
I can easily write a statement to return all users who have entered a timesheet with a Week_Ending_Date of e.g. 10/08/2012. However, if I try to return a list of all those who have not enetered a timesheet for 10/08/2012, I pick up every single timesheet in the table which does not have that date, so, for example, if a person has submitted 100 timesheets and only 1 of them is for 10/08/2012, the results will show him 99 times.
What I need is a fixed list of everyone on the Staff_Table who has not submitted for that date, showing once only.
I tried a Union with NOT EXISTS but either I'm doing it wrong or it simply isn't appropriate.
Can anyone point me in the right direction?
You should select all employee numbers that do not enter timesheet first. Then, filter the list using NOT IN.
DECLARE #Week_Ending_Date DATETIME = '2012-08-10'
DECLARE #Staff TABLE
(
EmployeeNo INT NOT NULL,
EmployeeName NVARCHAR(100) NOT NULL
)
DECLARE #TimeSheet TABLE
(
EmployeeNo INT NOT NULL,
Week_Ending_Date DATETIME
)
INSERT INTO #Staff (EmployeeNo, EmployeeName)
VALUES (1, 'Alan'), (2, 'Peter')
INSERT INTO #TimeSheet (EmployeeNo, Week_Ending_Date)
VALUES (1, '2012-08-10'), (1, '2012-08-17'), (2, '2012-08-03')
SELECT
S.EmployeeName
FROM
#Staff S
WHERE
EmployeeNo NOT IN (SELECT EmployeeNo FROM #TimeSheet WHERE Week_Ending_Date = #Week_Ending_Date)
Try adding DISTINCT to your query
ie
SELECT DISTINCT ...
Your query should look something like
SELECT *
FROM Staff
WHERE NOT EXISTS
(
Select EmployeeNo
from Timesheet
where WeekEndingDate='2012-08-10'
and TimeSheet.EmployeeNo = Staff.EmployeeNo
)
or
SELECT *
FROM Staff
WHERE EmployeeNo NOT IN
(
Select EmployeeNo
from Timesheet
where WeekEndingDate='2012-08-10'
)
You could use a not exists clause to find staff that has not submitted a particular timesheet:
select *
from Staff s
where not exists
(
select *
from Timesheet t
where t.EmployeeNo = s.EmployeeNo
and t.Week_Ending_Date = '2012-08-19'
)
Can you not just select all employees who haven't submitted a timesheet and group the results by their name?
select Name
from Staff_Table
left join Timesheet_Table on Staff_Table.[Employee No] = Timesheet_Table.[Employee No] and Timesheet_Table.Week_Ending_Date = '10 August 2012'
having Timesheet_Table.Week_Ending_Date is null
group by Name, Timesheet_Table.Week_Ending_Date
I haven't tested this, but something along these lines.