Getting null values when trying to join Two tables with Same Column Name - sql

Need some help
I have two tables CallsData and Plananumbers
I need to join them based on three conditions, SiteID, Date, Time
When I use the conditions SiteID and Date it's fine but when I add Time to the join condition I am getting NULL values.
Have changed the data type of all the columns to be Varchar, still no GO.
Have tried using the case statement to make sure I have the same set of values on both the table for Time column, no GO.
Please help.
Below is the query
SELECT A.[Date]
,A.[Time]
,A.[SiteID]
,A.[Split Skill]
,P.[ForOff]
,P.[HandlePlan]
,A.[ACD Calls]
,A.[ACCEPTABLE]
,A.[ABN Calls]
,A.[ACD Time]
,A.[ACW Time]
,A.[Hold Time]
,A.[Ring Time]
,A.[ANSTIME]
,A.[ABNTIME]
,A.[Service Level%]
,A.[SL Threshold]
,A.[Trans Out]
,A.[RONA]
,A.[Avail Time]
,A.[Staff Time]
,A.[Max Delay]
,A.[Short ABN]
,A.[Applied ACD]
FROM
[Stageing].[dbo].[Ac05CallsSiteIdTemp] as A
Left Join
Stageing.dbo.FinalPlanNumbersDemo as P on A.[Time] = P.[Time]

Id hazard a guess that there are no exact times between the tables.
Either try using a range of times OR
If just date (and not time) is important perhaps use just this part of each date, consider using the Date type.
If it is date and time try and reduce the precision of the time element.

Related

How can I get the first instance of an event per day with multiple columns including a datetime and return those columns plus the full datetime value?

I need to generate a SQL script that will pull out Distinct entries using a number of columns, one of which is a datetime column. I am only interested in the first occurrence of the day per event and the query needs to span multiple days. The query will be run against a very large database and can potentially be returning hundreds of thousands of results if not millions. Therefore I need this script to be as efficient as possible as well. This will eventually be a script running in SSRS to pull access transactions.
I've tried using GROUP BY, DISTINCT, subqueries, FIRST, and such without success. All the examples I can find online don't have JOIN statements or calculated columns such as only gathering the date from a datetime field.
I've simplified the below script some to only pull one day and one door, but the prod will be multiple days and doors. This code returns the data I need, I don't care about the COUNT, but I also need to get the (DateAdd(minute,-(ServerLocaleOffset),ServerUTC)) field in my result set as well somehow. The problem is since it goes down to the second it makes all records DISTINCT.
DECLARE #Begin datetime2 = '4/10/2019',
#End datetime2 = '4/11/2019',
#Door varchar(max) = 'Front Entrance'
SELECT
CONVERT(VARCHAR(10), (DateAdd(minute,-(ServerLocaleOffset),ServerUTC)),101) AS 'Date'
,AJ.PrimaryObjectIdentity
,AJ.SecondaryObjectIdentity
,AJ.MessageType
,AJ.PrimaryObjectName
,AJ.SecondaryObjectName
,AP.Text13
,COUNT(*) AS 'Count'
FROM Access.JournalLogView AJ
LEFT OUTER JOIN Access.Personnel as AP on AP.GUID = AJ.PrimaryObjectIdentity
WHERE (MessageType like 'CardAdmitted' OR MessageType like 'CardRejected')
AND (DateAdd(minute,-(ServerLocaleOffset),ServerUTC)) BETWEEN #Begin AND #End
AND (SecondaryObjectName IN (#Door))
GROUP BY CONVERT(VARCHAR(10), (DateAdd(minute,-(ServerLocaleOffset),ServerUTC)),101)
,PrimaryObjectIdentity
,SecondaryObjectIdentity
,MessageType
,PrimaryObjectName
,SecondaryObjectName
,Text13
ORDER BY AJ.PrimaryObjectName
I want to get the columns called out in the SELECT statement plus the datetime which includes the second. Again I also want the most efficient way of pulling this data as well. Thank you very much.
Assuming PrimaryObjectIdentity is the primary key to find the personnel in JournalLogview and ServerLocaleOffset as the datetime column in that table,I have written down this:
DECLARE #Begin datetime2 = '4/10/2019',
#End datetime2 = '4/11/2019',
#Door varchar(max) = 'Front Entrance'
WITH cte
AS(
SELECT
ROW_NUMBER() OVER
(PARTITION BY PrimaryObjectIdentity,CONVERT(VARCHAR(10), (DateAdd(minute,-(ServerLocaleOffset),ServerUTC)),101) ORDER BY ServerLocaleOffset) AS row_num,
--whatever the columns you want here
*
FROM
Access.JournalLogView)
SELECT
DateAdd(minute,-(ServerLocaleOffset),ServerUTC)) AS 'DateTime'
,AJ.PrimaryObjectIdentity
,AJ.SecondaryObjectIdentity
,AJ.MessageType
,AJ.PrimaryObjectName
,AJ.SecondaryObjectName
,AP.Text13
--I guess count(*) won't be of use a we are selecting only the first row
,COUNT(*) AS 'Count'
FROM cte AJ
LEFT OUTER JOIN
Access.Personnel as AP
on
AP.GUID = AJ.PrimaryObjectIdentity
WHERE
AJ.row_num = 1
AND (MessageType like 'CardAdmitted' OR MessageType like 'CardRejected')
AND (DateAdd(minute,-(ServerLocaleOffset),ServerUTC)) BETWEEN #Begin AND #End
AND (SecondaryObjectName IN (#Door))
GROUP BY (DateAdd(minute,-(ServerLocaleOffset),ServerUTC))
,PrimaryObjectIdentity
,SecondaryObjectIdentity
,MessageType
,PrimaryObjectName
,SecondaryObjectName
,Text13
ORDER BY AJ.PrimaryObjectName
In this query, I have used PARTITION to partition the whole table by each user, date and then assign row_number() to each row starting from the first entry of each user in that particular date. So, any row with row_num() = 1 will give you the first entry of that user in that date (which is the same condition I have used in the where clause). Hope this helps :)

Syntax of MS Access/SQL sub-query including aggregate functions

I am trying to produce a database to manage maintenance of equipment. I have two tables:
One (Inventory) containing details of each piece of equipment, including Purchase Date and Service Period,
One containing details of work done (WorkDone), including the date the work was carried out (Work Date).
I would like a query that displays the date that it should be next serviced. So far I have:
SELECT Max(DateAdd('m', [Inventory].[Service Period],
[WorkDone].[Work Date])) AS NextServiceDate,
Inventory.Equipement
FROM Inventory INNER JOIN WorkDone ON Inventory.ID = WorkDone.Equipment
GROUP BY Inventory.Equipement
This works well as long as some work done has been registered for a given piece of equipment. If no work has been carried out I would like the NextServiceDate to also show
DateAdd('m',[Inventory].[Service Period], [Inventory].[Purchase Date])
However, I cannot work out how to get SQL/MS access to compare two values and only display the greater of the two. From reading around I think I should be able to do a sub-query, but I cannot work out how to phase it.
I've been trying to adapt #MikeTeeVee's answer from here: Is there a Max function in SQL Server that takes two values like Math.Max in .NET?. But I keep getting errors saying that query is not part of an aggregate function and I'm not certain what I doing wrong. For example, I tried:
SELECT Inventory.Equipement,
(SELECT MAX(NSD_proxy)
FROM (VALUES
(Max(DateAdd('m', Inventory.[Service Period], WorkDone.[Work Date]))),
(DateAdd('m', Inventory.[Service Period], Inventory.[Purchase Date])))
AS FUNCTION(NSD_proxy)
) AS NextServiceDate,
FROM Inventory INNER JOIN WorkDone ON Inventory.ID = WorkDone.Equipment
GROUP BY Inventory.Equipement
which has some syntax error.
Consider a LEFT JOIN to return matched or unmatched records where latter is filled with NULLs, and then run your aggregate, MAX, with an NZ():
SELECT Max(NZ(DateAdd('m', i.[Service Period], w.[Work Date]),
DateAdd('m', i.[Service Period], i.[Purchase Date]))
) AS NextServiceDate, i.Equipement
FROM Inventory i LEFT JOIN WorkDone w ON i.ID = w.Equipment
GROUP BY i.Equipement
You don't have to compare the two dates, just check if a WorkDone record exists to match the Inventory record.
You can use:
IIF(ISNULL(WorkDone.Equipment),
DateAdd('m',[Inventory].[Service Period],[Inventory].[Purchase Date]),
Max(DateAdd('m',[Inventory].[Service Period],[WorkDone].[Work Date])))
AS NextServiceDate
The rest of your query can remain as is.

Reference Date 2 Months Prior Access SQL

I'm doing a Self Join, but having trouble doing it with dates. I have a date column, mm/dd/yyyy in intervals of a month (1/1/2006, 2/1/2006,...) and a number column of a variety of numbers. See code below...
SELECT t.ADate,
Sum(pre.liquid)/3 AS IP90
FROM [Table2] t
LEFT JOIN [Table2] pre ON pre.ADate >= (t.ADate -3)
AND pre.ADate <= t.ADate
GROUP BY t.ADate;
I'm taking the average of the records 2 months prior to the current date and the current date. So, for 5/1/2006 I want the average amount of liquid for 3/1/2006, 4/1/2006, and 5/1/2006. How can I do that in my code? Thank you.
Can you specify the dates in the query? Also I believe there is an average function in Access.
SELECT AVG(pre.liquid) As IP90
FROM [Table2] t
LEFT JOIN [Table2] pre
ON pre.ADate = t.ADate
WHERE t.ADate BETWEEN '3/1/2006' AND '5/1/2006';
Note you might have to give the dates a bit of leeway depending on the date values.

SQL Query, return value from table with no common key

I'm hoping for an idea on the best way to approach what I'm trying to do.
I have a table with a list of transactions. Each transactions has a PostDate in DateTime format. I have another table holding the fiscal period values. This table has the following columns; FiscalYear, FiscalMonth, StartDate, EndDate.
I'm trying to write a query that will return all values from my transactions table, along with the FiscalYear and FiscalMonth of the PostDate. So I guess I'm just trying to return the FiscalYear and FiscalMonth values when the PostDate falls between the StartDate and EndDate.
I've tried using a Subbuery, but I have little experience with them and kept returning an error message that the subquery was returning more than 1 value. Help would be appreciated
EDIT: Sorry, here is the query I tried. I also changed the title from "with no join", to "with no common key" to more accurately reflect my problem
SELECT Transactions.PostDate, Transactions.TranKey, Transactions.CustKey,
(SELECT FiscalPeriod.FiscPer
FROM FiscalPeriod
WHERE (Transactions.PostDate > CONVERT(Datetime, FiscalPeriod.StartDate, 102)) AND (Transactions.PostDate < CONVERT(DATETIME, FiscalPeriod.EndDate, 102))) AS FisPer
FROM Transactions
You should be able to eliminate the subquery and use a join like this:
SELECT Transactions.PostDate, Transactions.TranKey, Transactions.CustKey, FiscPer
FROM Transactions
INNER JOIN FiscalPeriod ON (PostDate BETWEEN StartDate AND EndDate)
although this is not quite the same - the subquery will show all the records even if the postdate isn't covered by the fiscal table, if you want that, change this join to a LEFT JOIN.
Maybe you need to join this two tables with something in common, or doing something like this:
SELECT Transactions.PostDate, Transactions.TranKey, Transactions.CustKey,
(SELECT **distinct** FiscalPeriod.FiscPer
FROM FiscalPeriod
WHERE (Transactions.PostDate > CONVERT(Datetime, FiscalPeriod.StartDate, 102)) AND (Transactions.PostDate < CONVERT(DATETIME, FiscalPeriod.EndDate, 102))) AS FisPer
FROM Transactions
remember, if you had this :
2004-01
2004-02
2004-03
for the fiscalperiod.FiscPer the distinct keyword will not work

SELECT with MAX and SUM from multiple tables

I have 3 tables :
weather_data (hourly_date, rain)
weather_data_calculated (hourly_date, calc_value)
weather_data_daily (daily_date, daily_value)
I would like to get a list of DAILY value from these 3 tables using this select :
SELECT daily_date, daily_value, SUM(rain), MAX(calc_value)
The SUM and the MAX need to be done for all the hour of the day.
This is what I did :
SELECT
date_format(convert_tz(daily_date, 'GMT', 'America/Los_Angeles'), '%Y-%m-%d 00:00:00') as daily_date_gmt,
daily_value,
SUM(rain),
MAX(calc_value)
FROM weather_data_daily wdd, weather_data wd, weather_data_calculated wdc
WHERE daily_date_gmt=date_format(convert_tz(wd.hourly_date, 'GMT', 'America/Los_Angeles'), '%Y-%m-%d 00:00:00')
and daily_date_gmt=date_format(convert_tz(wdc.hourly_date, 'GMT', 'America/Los_Angeles'), '%Y-%m-%d 00:00:00')
group by daily_date_gmt
order by daily_date_gmt;
This didn't work because I don't know how to deal with the group by in this case.
I also try to use a temporary table but without success too.
Thanks for your help!
Either include daily_value in your group by, or use two queries. One will contain the date column and the two aggregates, the other will contain the date column and daily value. you can then use a single outer query to join these result sets on the date column.
EDIT: You say in your comment that including daily_value in the group by means the query doesn't complete. This is because (probably) you have no join criteria between all the tables your query includes. This will result in a potentially VERY large result set which would take a very long time. I don't mind helping with the actual SQL but you will need to update your question so that we can see which fields are coming from which tables.
Assuming you only have one entry for daily_date, daily_value in 'weather_data_daily' you should
GROUP BY daily_date, daily_value, then your aggregrations (SUM and MAX) will operate on the correct grouping.
try this:
select a.daily_date, a.daily_value, SUM(b.rain), MAX(c.calc_value)
from weather_data_daily a,weather_data b,weather_data_calculated c
where convert(varchar, a.daily_date, 101)=convert(varchar, b.hourly_date, 101)
and convert(varchar, a.daily_date, 101)=convert(varchar, c.hourly_date, 101)
group by a.daily_date, a.daily_value
You have to connect the tables together somehow (this uses an inner join). This requires getting the hourly dates and other dates in the same format. This gives them the format MM/DD/YYYY.