How to solve this with SQL? - sql

I have a query which I have to modify in order to meet some new specifications:
The big picture of the query is below:
I have a few INNER JOINS which make up the result set of INNER JOINS, then that result set is LEFT JOINED with A1 first, then secondly with SCH. This is the current state of the query.
Now, what I have to do is add anoter result set, A2 which for the common part of A1 and A2 (the yellow part), to display the records with the current conditions in the GROUP BY.
My problem is that I still have to display SOME of the records in the blue area (which are common with the initial set, but not common with the new set which I am adding).
I do not know how can I refference those records that are in the blue arrea and FILTER them out (choose those which meet only one condition), without filtering records from A2. I do not know what kind of JOIN to use for A2 (I think I should use INNER JOIN, but I am not sure, that is why there is a ? mark on my diagram).
FILTER blue -> ALL yellow

I don't know if you are trying to do all in one single query or even if is it possible. Otherwise I think you should use a query like
SELECT your,fields
FROM (table/subquery)
WHERE keyfield
IS NOT IN (table/subquery)
to select the blue part of data

According to your diagram you want something like this:
SELECT * FROM InnerJoins -- whatever the previous inner joins are
INNER JOIN A1 ON A1.Key = InnerJoins.Key
INNER JOIN SCH ON SCH.Key = InnerJoins.Key
-- Do all inner joins up to here
-- the statement up to here includes the blue and yellow areas only
LEFT OUTER JOIN A2 ON A2.Key = InnerJoins.Key
-- this still includes the blue and yellow areas combined
WHERE A2.Key IS NULL
-- now we are excluding the yellow area as we are asking for the bits where we have no match in A2.

Related

Access DB engine does not recognize field when using Crosstab and subquery joins

I am in MS Access trying to join two queries. The first query is a Crosstab query:
TRANSFORM Sum(Q1.Downtime) AS SumOfDowntime
SELECT Q1.Batch
FROM [QryDowntime] Q1
GROUP BY Q1.Batch
PIVOT Q1.Category;
This runs, no issues. It is summing downtime for OEE for context. Output looks something like:
Batch Availability Performance Quality
1 0 5 2
2 3 1 5
...
I then have a separate query that pulls the date from the previous record:
SELECT B2.Batch,
(SELECT TOP 1 B1.LastPallet
FROM TblBatches AS B1
WHERE B1.ID < B2.ID
ORDER BY B1.ID DESC) AS PrevEnd
FROM TblBatches AS B2;
Again, no issues. This runs and the output looks something like:
Batch PrevEnd
1 8/2/2021
2 8/5/2021
...
I have a summary table and want to join these two.
SELECT B1.Batch,
Q1.Availability,
Q1.Performance,
Q1.Quality,
Q2.PrevEnd
FROM (TblBatches AS B1
LEFT JOIN QryCrosstab AS Q1 ON B1.Batch = Q1.Batch)
LEFT JOIN QryDate AS Q2 ON B1.Batch = Q2.Batch;
I thought this would be the easy part but I get the error "The Microsoft Access database engine does not recognize 'B2.ID' as a valid field name or expression." If I remove either of the joins, the query works fine.
I am aware of this solution but, as the author states, it is not really a solution. I do not want to use more tables if there is another way to fix the error.
I tried this solution but it is not quite the same. I don't really have a subquery I can do beforehand. If I can, I do not know how to do it. There is nothing dynamic. I am not accepting user inputs. These are straightforward queries. I am hoping there is a strange typo or incorrect syntax.
Any ideas would be greatly appreciated!

MS Access 2013, How to add totals row within SQL

I'm in need of some assistance. I have search and not found what I'm looking for. I have an assigment for school that requires me to use SQL. I have a query that pulls some colunms from two tables:
SELECT Course.CourseNo, Course.CrHrs, Sections.Yr, Sections.Term, Sections.Location
FROM Course
INNER JOIN Sections ON Course.CourseNo = Sections.CourseNo
WHERE Sections.Term="spring";
I need to add a Totals row at the bottom to count the CourseNo and Sum the CrHrs. It has to be done through SQL query design as I need to paste the code. I know it can be done with the datasheet view but she will not accept that. Any advice?
To accomplish this, you can union your query together with an aggregation query. Its not clear from your question which columns you are trying to get "Totals" from, but here's an example of what I mean using your query and getting counts of each (kind of useless example - but you should be able to apply to what you are doing):
SELECT
[Course].[CourseNo]
, [Course].[CrHrs]
, [Sections].[Yr]
, [Sections].[Term]
, [Sections].[Location]
FROM
[Course]
INNER JOIN [Sections] ON [Course].[CourseNo] = [Sections].[CourseNo]
WHERE [Sections].[Term] = [spring]
UNION ALL
SELECT
"TOTALS"
, SUM([Course].[CrHrs])
, count([Sections].[Yr])
, Count([Sections].[Term])
, Count([Sections].[Location])
FROM
[Course]
INNER JOIN [Sections] ON [Course].[CourseNo] = [Sections].[CourseNo]
WHERE [Sections].[Term] = “spring”
You can prepare your "total" query separately, and then output both query results together with "UNION".
It might look like:
SELECT Course.CourseNo, Course.CrHrs, Sections.Yr, Sections.Term, Sections.Location
FROM Course
INNER JOIN Sections ON Course.CourseNo = Sections.CourseNo
WHERE Sections.Term="spring"
UNION
SELECT "Total", SUM(Course.CrHrs), SUM(Sections.Yr), SUM(Sections.Term), SUM(Sections.Location)
FROM Course
INNER JOIN Sections ON Course.CourseNo = Sections.CourseNo
WHERE Sections.Term="spring";
Whilst you can certainly union the aggregated totals query to the end of your original query, in my opinion this would be really bad practice and would be undesirable for any real-world application.
Consider that the resulting query could no longer be used for any meaningful analysis of the data: if displayed in a datagrid, the user would not be able to sort the data without the totals row being interspersed amongst the rest of the data; the user could no longer use the built-in Totals option to perform their own aggregate operation, and the insertion of a row only identifiable by the term totals could even conflict with other data within the set.
Instead, I would suggest displaying the totals within an entirely separate form control, using a separate query such as the following (based on your own example):
SELECT Count(Course.CourseNo) as Courses, Sum(Course.CrHrs) as Hours
FROM Course INNER JOIN Sections ON Course.CourseNo = Sections.CourseNo
WHERE Sections.Term = "spring";
However, since CrHrs are fields within your Course table and not within your Sections table, the above may yield multiples of the desired result, with the number of hours multiplied by the number of corresponding records in the Sections table.
If this is the case, the following may be more suitable:
SELECT Count(Course.CourseNo) as Courses, Sum(Course.CrHrs) as Hours
FROM
Course INNER JOIN
(SELECT DISTINCT s.CourseNo FROM Sections s WHERE s.Term = "spring") q
ON Course.CourseNo = q.CourseNo

Record count when a certain value is present in one row and a different value is not present in another row

I have been tasked with a query that would tell me how many of a certain value are present when another value is not present in a separate row. The 2 rows do have a common field that will be the same when both are present. I have got to the following.
SELECT inci_no, count(inci_no)
FROM inc_unit
WHERE unit IN ('E08','ms08') and alm_date>='01/01/2013'
GROUP BY inci_no
So this gives me the number row for inci_no. I only need rows that have a 1 and the only unit is E08. The inci_no does not matter I have simply been using it to group by.
Thanks for your help.
As Robert said above you could write a self join. If I understand correctly, you want rows where unit is E08 and the second row is not ms08? If so, something like this might work:
Select t1.inci_no, count(t1.inci_no)
From inc_unit as t1 Inner Join inc_unit as t2 On t1.inci_no = t2.inci_no
Where t1.unit = 'E08' and t2.unit <> 'ms08' and t1.alm_date>='01/01/2013'
Group by t1.inci_no
You might have to add something to exclude joining on itself, but this should get you started.

Find related "ordered pairs" in SQL

Let's say I have a table format that looks exactly like this:
I'd like to write a query that locates the maximum station for a given frame and output case (results are grouped by frame & output case) but also return the ordered P (& eventually V2, V3, T, M2 & M3) that would be associated with the maximum station. The desired query is shown below:
I can't for the life of me figure this out. I've posted a copy of the access database to my google drive: https://drive.google.com/folderview?id=0B9VpkDoFQISJOFcwS2RMSGJ5RVk&usp=sharing
select x.*, t.p
from (select frame, outputcase, max(station) as max_station
from tbl
group by frame, outputcase) x
inner join tbl t
on x.frame = t.frame
and x.outputcase = t.outputcase
and x.max_station = t.station
order by x.frame, x.outputcase;
Just as a note to avoid confusion, w/ that second column, t is the table alias, p is the column name.
The subquery, which I've assigned an alias of x, finds the max(station) for each unique combination of (frame, outputcase). That is what you want, but the problem does not stop there, you also want column p. The reason that couldn't be selected in the same query is because you would have had to group by it, and you don't want the max(station) for each combination of (frame, outputcase, p). You want the max(station) for each combination of (frame, outputcase).
Because we couldn't get column p in that first step, we have to join back to the original table using the value we obtained (which I've assigned an alias, max_station), and the obvious join conditions of frame and outputcase. So we join back to the original table on those 3 things, 2 of which are fields on the actual table, one of which was calculated in the subquery (max_station).
Because we've joined back to the original table, we can then select column p from the original table.
Takes a bit to return the query, but the result below provides the desired result:
SELECT t1.*
FROM [Element Forces - Frames] as t1
WHERE t1.Station In (SELECT TOP 1 t2.Station
FROM [Element Forces - Frames] as t2
WHERE t2.Frame = t1.Frame
ORDER BY t2.Station DESC)
ORDER BY t1.Frame ASC, t1.OutputCase ASC;
I still want to thank everyone who posted answers. I'm sure it's just syntax errors on my part that I was struggling with.

Non blank cell count for a particular row in dynamic colums in ssrs with matrix

I have a SQL query like this
SELECT sam.AREATOPICID,
sec.SURVEYSECTION,
us.USERSURVEYID,
us.SURVEYAREATOPICID,
us.USERID,
usr.SURVEYUSERNAME,
us.COMMENT
FROM USERSURVEY us
INNER JOIN USERS usr
ON us.USERID = usr.USERID
INNER JOIN SURVEYAREATOPICMAPDEMO sam
ON sam.AREATOPICID = us.SURVEYAREATOPICID
INNER JOIN SECTION sec
ON sam.SURVEYSECTIONID = sec.SURVEYSECTIONID
ORDER BY us.USERID,
sam.AREATOPICID,
SURVEYSECTION
Now, in SSRS I want to display report like this
Now for comment, I want in a particular row how many users have comment on it. This field only have to show count of comments that are not blank and for a particular row(i.e. question).
I have done for user1, user2 .., type of column but I am not able to count the comment.
When you create your matrix, there are row (your question), column (your user) and a data cell (sum(COMMENT))in it. Right-click it and you should get Add Total menu item. Use it to add a column total. Then you can position that column to an appropriate location in your table.
EDIT
For counting records you use COUNT() like COUNT(Fields!Comment.Value)
For counting non-empty/null values use:
SUM(IIF(IsNothing(Fields!Comment.Value) OR (Fields!Comment.Value = ""),0,1))