MAX Function Fails in SQL - sql

I'm trying to get the MOST recent date that comes before tom_temp.Begin_Time out of tbl_Trim_history.Comp. The SQL I'm using is:
SELECT
Tom_Temp2.feeder,
Tom_Temp.CauseType,
Tom_Temp.RootCause,
Tom_Temp.Storm_Name_Thunder,
Tom_Temp.DeviceGroup,
tbl_Trim_History.[COMP],
Tom_Temp.[Begin_Time]
FROM Tom_Temp2
LEFT JOIN (Tom_Temp
LEFT JOIN tbl_Trim_History
ON Tom_Temp.feeder = tbl_Trim_History.CIRCUIT_ID)
ON Tom_Temp2.feeder = Tom_Temp.feeder
WHERE (((tbl_Trim_History.[COMP]) < [Tom_Temp].[Begin_Time]));
I'm having a hard time figuring out where I need to put my max() function in this statement in order to make sure I don't get back every single tbl_Trim_history.[COMP] that occurs prior to the tom_temp.Begin_Time date. I only want the most recent date from tbl_Trim_history.[COMP] that occurs BEFORE the tom_temp.begin_Time .... NOT every historical date record.
Any help you guys could give me would be awesome because I keep getting back sets that I can tell are not what I'm looking for / expecting.
Thanks everyone. I appreciate the feedback.
Edit in regard to the responses below:
Due to the character limits, I just edited the master post for you guys.
I can't really post the data as it is somewhat confidential, so the best I can do is give you an example. Also, this is access, but my background is MySQL. Sorry for the tags, I wasn't sure what was similar since the access tag just didn't seem to fit the question.
The Data being received are about 168 records. Someone pointed out that there is an inner join occurring here, but I wanted to indicate I'm actually using 3 different tables.
1 table contains my feeders,
Another contains a list of all outages that I am joining to using all my feeders contained in the first table
Then I have another table that contains all the trim history for each feeder. The outage table is joined to the trim table.
When I run the query above, I get data like this
feeder | comp | Begin_time
___________________________________________
123456 | 10/4/2012 | 3/3/2016 11:26:00AM
123456 | 10/17/2015 | 3/3/2016 11:26:00AM
456789 | 6/28/2008 | 9/20/2013 10:05AM
456789 | 12/1/2012 | 9/20/2013 10:05AM
456789 | 7/3/2013 | 9/20/2013 10:05AM
what I want is data like this:
feeder | comp | Begin_time
___________________________________________
123456 | 10/17/2015 | 3/3/2016 11:26:00AM
456789 | 7/3/2013 | 9/20/2013 10:05AM
where the comp date is the closest to date / time occuring BEFORE Begin_time date.
I tried this query:
SELECT Tom_Temp2.feeder, Tom_Temp.CauseType, Tom_Temp.RootCause, Tom_Temp.Storm_Name_Thunder, Tom_Temp.DeviceGroup, Max(tbl_Trim_History.COMP) AS MaxOfCOMP, Tom_Temp.Begin_Time
FROM Tom_Temp2
LEFT JOIN (Tom_Temp LEFT JOIN tbl_Trim_History ON Tom_Temp.feeder = tbl_Trim_History.CIRCUIT_ID) ON Tom_Temp2.feeder = Tom_Temp.feeder
GROUP BY Tom_Temp2.feeder, Tom_Temp.CauseType, Tom_Temp.RootCause, Tom_Temp.Storm_Name_Thunder, Tom_Temp.DeviceGroup, Tom_Temp.Begin_Time
HAVING (((Max(tbl_Trim_History.COMP))<[Tom_Temp].[Begin_Time]));
But of the 168 records I get back in my first query, I'm only getting back 20 records with this query.
The reason I know this is wrong is because some records are missing between the set of 168 and the set of 20. For example, I'd be missing any records for feeder 456789. However, I know this record should be returned because it's in my table of feeders that should be returned (Tom_Temp2).
After manually deleting unwanted rows of data, I know that I should get a record count of 85. So my most recent attempt to use the Max query is way off.

Related

Union results either Blank or Unfiltered

We have data that separates Paid and Rejected claims. I need to see results of both and therefore have to do a union.
(Our data is a mess. I am also aliasing for confidentiality/HIPPA compliance. Please try not to get hung up on those parts because I can't change it.)
SELECT CustID, code, date, 'Paid' AS Srce
FROM Paid.Claims
INNER JOIN Paid.Medical
ON Paid.Claims.id = Paid.Medical.id
AND Paid.Claims.blind = Paid.Medical.blind
WHERE Paid.Claims.date BETWEEN '2022-01-01' AND '2022-06-07'
AND Paid.Medical.code IN ('88521','88522','88523','88524','88525')
AND Paid.Claims.custID IN ('N065468','N095843','N001086')
UNION
SELECT CustID, code, date, 'Filter' AS Srce
FROM Rejected.Claims
INNER JOIN Rejected.Medical
ON Rejected.Claims.id = Rejected.Medical.id
AND Rejected.Claims.blind = Rejected.Medical.blind
WHERE Rejected.Claims.date BETWEEN '2022-01-01' AND '2022-06-07'
AND Rejected.Medical.code IN '88521','88522','88523','88524','88525')
AND Rejected.Claims.custID IN ('N065468','N095843','N001086')
It's based on a query that the person before me made, and that one works but it's also much simpler because it pulls less from less places. My outcomes so far have been:
Leave the where-clause out of the Paid data but still in the Rejected data and get EVERY RESULT. None of the filtering seems to be working.
Include the where-clause in both and get no results. filtering not working, but in the opposite direction.
I have also tried
SELECT *
FROM (
everything above with and without filters
) AS results
WHERE <filters same as above>
And results set is empty.
I have tried with and without aliasing with no changes in what's returned.
I'm expecting about 200 results that SHOULD look something like this:
| CustID | code | date | Srce |
| ------- | ----- | ---------- | ------ |
| N065468 | 88522 | 2022-04-04 | Paid |
| N095843 | 88521 | 2022-03-09 | Paid |
| N001086 | 88524 | 2022-05-20 | Filter |
Back to troubleshooting.
It's hard without sample data as someone else has requested. Without any data I'd recommend running each query individually and seeing what results you get ie. If you run just the top half for paid claims does that give you the rows you're expecting? Then the bottom half? The filtering arguments can be case sensitive so I'd recommend checking your medical codes are lower case.
We have many duplicate fields as a result of our flattening process. My formatting may have been correct, but it turns out I was pulling from some of the wrong places. I solved the problem by creating a franken-query using several others made by my predecessor with a similar union element. Depending on how I was attempting to alias everything, the filters were likely pulling from different fields than the ones I was select-ing.

Selecting limited results from two tables

I apologise if this has been asked before. I'm still not certain how to phrase my question for the title, so wasn't sure what to search for.
I have a hundred or so databases in the same instance, one for each of my customers, named for the customer, and they all have the same structure. I want to select a single result set that includes the database name along with the most recent date entry in one of the tables. I can pull the database names from sys.databases, but then for each database I want to select the most recent date from Events.Date_Logged so that my result set looks something like this:
_______________________________
| | |
|Cust_Name |Latest_Event |
|_______________|_______________|
| | |
|Customer1 |01/02/2020 |
|_______________|_______________|
| | |
|Customer2 |02/02/2020 |
|_______________|_______________|
| | |
|Customer3 |03/02/2020 |
|_______________|_______________|
I'm really struggling with the syntax though. I either get just a single row returned or every single event for each customer. I think my joins are as rusty as hell.
Any help would be appreciated.
What I suggest you do:
Declare a result variable (of type table)
Use a cursor to go over every database
Inside the cursor: do a select top 1 ... order by date desc to get the most recent record. Save this result in the result variable.
After the cursor print the result variable.
That should do the trick.

Access query, if two values exist in one column, omit one

I have a series of queries that generate reports that contain chemical data. There are two compounds A and B where A is the total amount and B is a speciated amount (like total iron and ferrous iron, for example).
There are about one hundred total compounds in the query result, and I need a criteria to filter the results such that if both Compounds A and B are present, only Compound B is displayed. So far I've tried adding a few iif statements to the criteria section in the query builder with no luck.
Here is what I have so far:
SELECT Table1.KEY_ANLT
FROM Table1
WHERE (((Table1.KEY_ANLT)=IIf([Table1].[KEY_ANLT]=1223 And [Table1].[KEY_ANLT]=70,70,1223)));
This filters out Compound A but does not include the rest of the compounds. How can I modify the query to also include the other compounds?
So, to clarify some of the comments above, the problem here is you don't have (or haven't specified above) a way to identify values that go together. You gave 70 and 1223 as an example, but if you gave us a list of all the numbers, how would we be able to identify which ones go together? You might say "chemistry expertise", but that's based on another column with the compounds' names, right? So really, your query should use that column. But then there's still the problem of how to connect associated names (e.g., "total iron" and "ferrous iron" might be connected because they both have the word "iron", but what about "permanganate" and "manganese"?). In short, you need another column to specify the thing in common between these separate rows, whether it's element, ion, charge, etc. You would also need a column identifying which row in each "group" you would want to include in your query (or, which ones to exclude). For example:
+----------+-----------------+---------+---------+
| KEY_ANLT | Compound | Element | Primary |
+----------+-----------------+---------+---------+
| 70 | total iron | Fe | Y |
| 1223 | ferrous iron | Fe | |
| 1224 | ferric iron | Fe | |
| 900 | total manganese | Mn | Y |
| 901 | permanganate | Mn | |
+----------+-----------------+---------+---------+
Then, to get a query that shows just the "primary" rows, it's pretty trivial:
SELECT * FROM Table1 WHERE Primary='Y';
Without that [Primary] column, you'd have to decide how to choose each row. Perhaps you'd want the one with the smallest KEY_ANLT?
SELECT Table1.*
FROM
(SELECT Element, min(KEY_ANLT) AS MinKey FROM Table1 GROUP BY Element) AS Subquery
INNER JOIN Table1 ON
Subquery.Element=Table1.Element AND
Subquery.MinKey=Table1.KEY_ANLT
The reason your query doesn't work is that the WHERE clause operates row-by-row, and doesn't compare different rows to one another. So in your SQL:
IIf([Table1].[KEY_ANLT]=1223 And [Table1].[KEY_ANLT]=70,70,1223)
NONE of the rows will evaluate this as 70, because no single row has KEY_ANLT=1223 AND KEY_ANLT=70. Each row only has one value for KEY_ANLT. So then that IIF expression evaluates as 1223 for every row, and your condition will only return rows where KEY_ANLT=1223 (compound B).

Access Join Query

I have two tables tbl_DaysWeeksMonths (Left Table) and tbl_Telephony (Right Table). tbl_DaysWeeksMonths has a record of every day of the year with columns (Row_Date/Week/Month) whilst tbl_Telephony has telephony data for hundreds of agents by day with columns (row_date/agent/calls/talk time)(Note: Each agent only has records for 5-6 days of the week instead of everyday).
I want to join the two tables so that each agent has a record for every day of the week regardless if they took calls on a day or not. I want to display blank records (except for the date field) for days which consultants did not take calls. E.g:
## Date ## ## Agent ## ## Calls ## ## Talk Time ##
1. 26/05/2012 | James | 40 | 560
2. 27/05/2012 | James | |
3. 28/05/2012 | James | 34 | 456
4. 29/05/2012 | James | |
5. 30/05/2012 | James | 40 | 643
6. 31/05/2012 | James | 36 | 345
7. 01/06/2012 | James | 31 | 160
I'm trying to use the below code but I don't think it's correct. Any suggestions on a better code to use. Please help.
SELECT tbl_DaysWeeksMonths.Row_Date,
[tbl_Telephony].Consultant,
[tbl_Telephony].i_acdtime
FROM tbl_DaysWeeksMonths
LEFT JOIN [tbl_Telephony]
ON tbl_DaysWeeksMonths.Row_Date = [tbl_Telephony].row_date;
Step 1 -- Assuming you have a table (say, named Consultants) that lists each distinct consultant, create a query (say, named Consultant Days) that generates all possible combinations of days and consultants. It might look something like this:
SELECT [Consultants].Consultant, tbl_DaysWeeksMonths.Row_Date
FROM [Consultants], tbl_DaysWeeksMonths;
If you don't have a Consultants table, you could substitute it with a query that selects the distinct consultants listed in tbl_Telephony. In other words, you can create a Consultants query that looks something like this:
SELECT DISTINCT Consultant FROM [tbl_Telephony];
Step 2 -- Create a query that outer joins tbl_Telephony to Consultant Days. It might look something like this:
SELECT [Consultant Days].Row_Date, [Consultant Days].Consultant, [tbl_Telephony].i_acdtime
FROM [Consultant Days]
LEFT JOIN [tbl_Telephony]
ON [Consultant Days].Consultant = [tbl_Telephony].Consultant
AND [Consultant Days].Row_Date = [tbl_Telephony].row_date;
This also assumes that the row_date values in tbl_Telephony match the Row_Date values in tbl_DaysWeeksMonths -- in other words, that row_date values in tbl_Telephony are whole days (that is, do not contain a time-of-day component). This also assumes that i_acdtime values in tbl_Telephony are the total talk time for the given consultant and day (as opposed to the talk time for a given call). Presumably there is another column in tbl_Telephony that will give the the total number of cals for the given consultant and day which you could add to the query to get the "Calls" column you said you wanted your question.
You can also use this query.
SELECT tbl_DaysWeeksMonths.Row_Date, [tbl_Telephony].Consultant, [tbl_Telephony].i_acdtime
FROM tbl_DaysWeeksMonths
LEFT OUTER JOIN [tbl_Telephony] ON tbl_DaysWeeksMonths.Row_Date = [tbl_Telephony].row_date;

Cumulative average number of records created for specific day of week or date range

Yeah, so I'm filling out a requirements document for a new client project and they're asking for growth trends and performance expectations calculated from existing data within our database.
The best source of data for something like this would be our logs table as we pretty much log every single transaction that occurs within our application.
Now, here's the issue, I don't have a whole lot of experience with MySql when it comes to collating cumulative sum and running averages. I've thrown together the following query which kind of makes sense to me, but it just keeps locking up the command console. The thing takes forever to execute and there are only 80k records within the test sample.
So, given the following basic table structure:
id | action | date_created
1 | 'merp' | 2007-06-20 17:17:00
2 | 'foo' | 2007-06-21 09:54:48
3 | 'bar' | 2007-06-21 12:47:30
... thousands of records ...
3545 | 'stab' | 2007-07-05 11:28:36
How would I go about calculating the average number of records created for each given day of the week?
day_of_week | average_records_created
1 | 234
2 | 23
3 | 5
4 | 67
5 | 234
6 | 12
7 | 36
I have the following query which makes me want to murderdeathkill myself by casting my body down an elevator shaft... and onto some bullets:
SELECT
DISTINCT(DAYOFWEEK(DATE(t1.datetime_entry))) AS t1.day_of_week,
AVG((SELECT COUNT(*) FROM VMS_LOGS t2 WHERE DAYOFWEEK(DATE(t2.date_time_entry)) = t1.day_of_week)) AS average_records_created
FROM VMS_LOGS t1
GROUP BY t1.day_of_week;
Halps? Please, don't make me cut myself again. :'(
How far back do you need to go when sampling this information? This solution works as long as it's less than a year.
Because day of week and week number are constant for a record, create a companion table that has the ID, WeekNumber, and DayOfWeek. Whenever you want to run this statistic, just generate the "missing" records from your master table.
Then, your report can be something along the lines of:
select
DayOfWeek
, count(*)/count(distinct(WeekNumber)) as Average
from
MyCompanionTable
group by
DayOfWeek
Of course if the table is too large, then you can instead pre-summarize the data on a daily basis and just use that, and add in "today's" data from your master table when running the report.
I rewrote your query as:
SELECT x.day_of_week,
AVG(x.count) 'average_records_created'
FROM (SELECT DAYOFWEEK(t.datetime_entry) 'day_of_week',
COUNT(*) 'count'
FROM VMS_LOGS t
GROUP BY DAYOFWEEK(t.datetime_entry)) x
GROUP BY x.day_of_week
The reason why your query takes so long is because of your inner select, you are essentialy running 6,400,000,000 queries. With a query like this your best solution may be to develop a timed reporting system, where the user receives an email when the query is done and the report is constructed or the user logs in and checks the report after.
Even with the optimization written by OMG Ponies (bellow) you are still looking at around the same number of queries.
SELECT x.day_of_week,
AVG(x.count) 'average_records_created'
FROM (SELECT DAYOFWEEK(t.datetime_entry) 'day_of_week',
COUNT(*) 'count'
FROM VMS_LOGS t
GROUP BY DAYOFWEEK(t.datetime_entry)) x
GROUP BY x.day_of_week