Error while creating query as a Missing operator? - sql

I am trying to extract data in a tabular format with different values for part-time and full-time, to get an output like this:
but my query generates this error:
syntax error missing operator
What operator is missing from this query?
SELECT
BANINST1_SZVIRST.SZVIRST_TERM_DESC,
Count(BANINST1_SZVIRST.SZVIRST_FULL_PART_IND="F") AS ["Full-time Undergraduate Enrollment"],
Count(IIf(BANINST1_SZVIRST.SZVIRST_FULL_PART_IND="P",1,Null)) AS ["Part-time Undergraduate Enrollment"]
FROM BANINST1_SZVIRST
GROUP BY
BANINST1_SZVIRST.SZVIRST_TERM_DESC,
BANINST1_SZVIRST.SZVIRST_TERM_CODE,
BANINST1_SZVIRST.SZVIRST_LEVL_CODE,
BANINST1_SZVIRST.SZVIRST_FULL_PART_IND
HAVING
(((BANINST1_SZVIRST.SZVIRST_TERM_CODE) In ("201020","201120","201220","201320","201420","201520","201620"))
AND ((BANINST1_SZVIRST.SZVIRST_LEVL_CODE)="01"));

I think you have 4 different conditions happening here that you are testing for:
Counts of people that are Full-Time
Counts of people that are Part-Time
Counts of people that are Graduate
Counts of people that are UnderGraduate
You are on the right track to use the iif() statement. I think that was from a previous question you asked a day or two ago. The iif() statements would be:
SUM(IIF(BANINST1_SZVIRST.SZVIRST_FULL_PART_IND="F", 1, 0)) as [FullTime],
SUM(IIF(BANINST1_SZVIRST.SZVIRST_FULL_PART_IND="P", 1, 0)) as [PartTime],
SUM(IIF(SZVIRST_LEVL_CODE="01", 1, 0)) as [Graduate],
SUM(IIF(SZVIRST_LEVL_CODE="02", 1, 0)) as [UnderGraduate],
I changed the COUNT() to a SUM() just because it feels more natural since the IIF() is returning a 1 or a 0. You could change that back to a COUNT(Iif(<condition>, 1, null)) and it would fine too.
Checking for two conditions
If you want to combine a couple of conditions to get a count, the formula changes slightly.
For insstance, if you wanted a count of all Full-Time People that are also Under Graduates you could use:
SUM(IIF(BANINST1_SZVIRST.SZVIRST_FULL_PART_IND="F" AND SZVIRST_LEVL_CODE="02", 1, 0)) AS [FullTimeUnderGraduates]
Here we put BOTH conditions INSIDE the first parameters of the IIF() formula. If both are TRUE, it returns a 1, then all those 1s gets summed up.
Lastly, if you are wanting to count/sum both Graduate and Under Graduates in your query, then you can't exclude them in your HAVING clause. So you'll need to remove the bit that reads:
((BANINST1_SZVIRST.SZVIRST_LEVL_CODE)="01")
Otherwise a test like
iif(BANINST1_SZVIRST.SZVIRST_LEVL_CODE="01", 1, 0)
will ALWAYS return a 1 and
iif(BANINST1_SZVIRST.SZVIRST_LEVL_CODE="02", 1, 0)
will ALWAYS return 0
Example
The following should run in your database and give you a good working example of the logic discussed above:
SELECT
BANINST1_SZVIRST.SZVIRST_TERM_DESC,
SUM(IIF(BANINST1_SZVIRST.SZVIRST_FULL_PART_IND="F", 1, 0)) as [FullTime],
SUM(IIF(BANINST1_SZVIRST.SZVIRST_FULL_PART_IND="P", 1, 0)) as [PartTime],
SUM(IIF(SZVIRST_LEVL_CODE="01", 1, 0)) as [Graduate],
SUM(IIF(SZVIRST_LEVL_CODE="02", 1, 0)) as [UnderGraduate],
SUM(IIF(BANINST1_SZVIRST.SZVIRST_FULL_PART_IND="F" AND SZVIRST_LEVL_CODE="02", 1, 0)) AS [FullTimeUnderGraduates],
SUM(IIF(BANINST1_SZVIRST.SZVIRST_FULL_PART_IND="P" AND SZVIRST_LEVL_CODE="02", 1, 0)) AS [PartTimeUnderGraduates],
SUM(IIF(BANINST1_SZVIRST.SZVIRST_FULL_PART_IND="F" AND SZVIRST_LEVL_CODE="01", 1, 0)) AS [FullTimeGraduates],
SUM(IIF(BANINST1_SZVIRST.SZVIRST_FULL_PART_IND="P" AND SZVIRST_LEVL_CODE="01", 1, 0)) AS [PartTimeGraduates]
FROM BANINST1_SZVIRST
GROUP BY
BANINST1_SZVIRST.SZVIRST_TERM_DESC,
BANINST1_SZVIRST.SZVIRST_TERM_CODE,
BANINST1_SZVIRST.SZVIRST_LEVL_CODE,
BANINST1_SZVIRST.SZVIRST_FULL_PART_IND
WHERE BANINST1_SZVIRST.SZVIRST_TERM_CODE IN ("201020","201120","201220","201320","201420","201520","201620")

Related

issue with using a Subquery with left join

I am having an issue while being left joining 2 tables using subquery, getting an error :
Msg 156, Level 15, State 1, Line 25
Incorrect syntax near the keyword 'FROM'.
Msg 102, Level 15, State 1, Line 36
Incorrect syntax near 'PM'.
Here is the query I was trying to achieve:
SELECT
 [SEASON],
SUM(B.QUANTITY) AS QUANTITY,
FROM
(SELECT
 QUANTITY, WAREHOUSE,
CASE SUBSTRING(sku, 3, 1)
WHEN '1' THEN 'SS'
ELSE 'FW'
END + SUBSTRING (sku, 1, 2) [SEASON]
FROM
Table
) B
As I stated in the comments, you have 2 FROM clauses. Presumably the latter should be a CROSS JOIN or CROSS/OUTER APPLY (we don't know which). You also alias your second derived table as PM and then alias the table PRODTABLE as PM; that isn't allowed either as you can't have 2 objects with the same alias in the same scope. As I can't guess what alias you mean in other locations, I put {Alias} in places you need to add the relevant alias.
I also remove the NOLOCK table hints; you didn't reply as to why you "need" them and with respect I doubt you understand what it does considering the comments and question; more likely you have picked up someone elses terrible habit (get rid of said bad habit now).
I also, finally, get rid of the other bad habit of single quote aliases (see my comment on that too) and schema qualify (assuming dbo):
SELECT {Alias}.[SEASON],
SUM(BL.QUANTITY) AS QUANTITY,
{Alias}.PRODUCT AS PRD_CLASS,
{Alias}.BRAND AS BRAND,
{Alias}.COST_PRICE AS COST,
{Alias}.DATECREATE
FROM (SELECT QUANTITY,
WAREHOUSE,
CASE SUBSTRING(EXTENDED, 3, 1)WHEN '1' THEN 'SS' ELSE 'FW' END + SUBSTRING(EXTENDED, 1, 2) AS [SEASON]
FROM dbo.BINLABE) BL
CROSS JOIN (SELECT PRODUCT AS PRDODUCT,
BRAND AS BRAND,
COST_PRICE AS COST,
DATECREATE AS DATE_CREATE
FROM dbo.PRODTABLE) PT
LEFT JOIN dbo.PRODTABLE PM ON BL.SKU = PM.SKU --Think we can safely assume this is PM
WHERE {Alias}.WAREHOUSE = '0001'
GROUP BY {Alias}.[SEASON]
ORDER BY {Alias}.[SEASON];

SQL query filter a row with a specific combination only

I am trying to query a table in which I have a specific condition, I do not want to query rows where Reference Category is Production and Issue is Sold.
In the above table, I want row 1,2& 4 only - How do I make such a query. If i do WHERE ReferenceCategory = 'Production line' AND Issue = 'Sold', it takes away row 4 as well.
http://sqlfiddle.com/#!18/f54f5b/1
I do not want to query rows where Reference Category is Production and [Issue is] Sold
You could simply phrase the conditions as follows:
WHERE NOT (ReferenceCategory = 'Production line ' AND Issue = 'Sold')
In your demo on DB Fiddle, this returns records 1, 2, 4.
Answered by #GMB:
SELECT *
FROM TransactionTable
WHERE NOT (ReferenceCategory = 'Production line' AND Issue = 'Sold')
For AX/D365 X++ user, the use of logical expression NOT(A and B) is not allowed in a X++ query range, therefore, transforming NOT(A and B) to its equivalent expression according to De'Morgans Law:
NOT(A and B) = (NOT A) OR (NOT B)
SELECT *
FROM TransactionTable
WHERE ReferenceCategory <> 'Production line' OR Issue <> 'Sold'**

Questsion about using HAVING in ACCESS SQL

I wanted to get clarity on how the HAVING component in an SQL statement works, particularly with a SQL statement that has multiple joins. Consider the following SQL select statement:
SELECT
p.id,
p.first_name as [First Name],
p.last_name as [Last Name]
FROM
( [tbl_person] as p
INNER JOIN [tbl_person_languages] as pl
ON [p].[id] = [pl].[person_id])
INNER JOIN [tbl_person_crossCuttingSkills] As ccp
ON [p].[id] = [ccp].[person_id]
WHERE
cint(pl.language_id) in (12,14) AND
cint(ccp.skill_id) in (55)
GROUP BY
p.id,
p.first_name,
p.last_name
HAVING
count(pl.language_id) =2 AND
count(ccp.skill_id) = 1
I want to pull out records, from tbl_person, where a record has all of the WHERE requirements. For example: I want to select all users where they speak a languages Italian (with ID 12) and Spanish (ID 15) AND have a skill of cooking (55). They need to have all requirements, not just one or more. I was under the assumption this is where you would use GROUP BY and HAVING. With the HAVING:
count(pl.language_id) =2
I use count = 2 because there are two options in the language WHERE clause (12 and 14)
And I use
count(ccp.skill_id) = 1
Because there is one value in the WHERE clause (55).
Is this the correct way to be doing this? For some reason, this returns no records (I have one record in my DB of a person who fits these requirements exactly). But, if I change my HAVING to:
count(pl.language_id) =2 AND
count(ccp.skill_id) = 2
It works fine. Why is this? Are my assumptions of how this works incorrect or is there something else going on?
Remember what count() does . . . it counts non-NULL values. So, you are counting two non-NULL values then the counts are the same.
In most dialects of SQL, you can fix this by doing:
HAVING count(distinct pl.language_id) = 2 AND count(distinct ccp.skill_id) = 1
But that doesn't work in MS Access, because MS Access does not support COUNT(DISTINCT).
So, you can be more verbose. In your case:
HAVING SUM(iif(cint(pl.language_id) = 12, 1, 0)) > 0 AND
SUM(iif(cint(pl.language_id) = 14, 1, 0)) > 0 AND
SUM(iif(cint(ccp.skill_id) = 55, 1, 0)) > 0
I'm sorry this HAVING clause is not simpler. You could switch to another database (such as SQL Server Express) that more closely aligns with ANSI functionality.

Merging two queries that are the same BUT their GROUP BY?

So as the title implies, I have the same exact structure for two queries but I just need to change the grouping. I know I can do a union, however, to narrow the script, is there a way to associate both grouping in one query? For example:
SELECT shtuff FROM report_tickets WHERE something = something GROUP BY companies
//Query two
SELECT shtuff FROM report_tickets WHERE something = something GROUP BY ticket_id
Can I do?:
SELECT * FROM report_tickets WHERE something = something GROUP BY companies AND ticket_id
I know this doesn't work but in concept. Have the query take in account both groupings? ^^
I would need to add the following to line 30 from the linked code below, this may determine if it can work or not.
SUM(IF(ROUND((SELECT difference)) < 1, 1, 0)) AS zero_to_one,
SUM(IF(ROUND((SELECT difference)) BETWEEN 1 AND 8, 1, 0)) AS one_to_eight,
SUM(IF(ROUND((SELECT difference)) BETWEEN 8 AND 24, 1, 0)) AS eight_to_twentyfour,
SUM(IF(ROUND((SELECT difference)) > 24, 1, 0)) AS over_twentyfour,

Trouble with SQL UNION operation

I have the following table:
I am trying to create an SQL query that returns a table that returns three fields:
Year (ActionDate), Count of Built (actiontype = 12), Count of Lost (actiontype = a few different ones)
Bascially, ActionType is a lookup code. So, I'd get back something like:
YEAR CountofBuilt CountofLost
1905 30 18
1929 12 99
1940 60 1
etc....
I figured this would take two SELECT statements put together with a UNION.
I tried the following below but it only spits back two columns (year and countbuilt). My countLost field doesn't appear
My sql currently (MS Access):
SELECT tblHist.ActionDate, Count(tblHist.ActionDate) as countBuilt
FROM ...
WHERE ((tblHist.ActionType)=12)
GROUP BY tblHist.ActionDate
UNION
SELECT tblHist.ActionDate, Count(tblHist.ActionDate) as countLost
FROM ...
WHERE (((tblHist.ActionType)<>2) AND
((tblHist.ActionType)<>3))
GROUP BY tblHist.ActionDate;
Use:
SELECT h.actiondate,
SUM(IIF(h.actiontype = 12, 1, 0)) AS numBuilt,
SUM(IIF(h.actiontype NOT IN (2,3), 1, 0)) AS numLost
FROM tblHist h
GROUP BY h.actiondate
You should not use UNION for such queries. There are many ways to do what you want, for example
Updated to fit access syntax
SELECT tblHist.ActionDate,
COUNT(SWITCH(tblHist.ActionType = 12,1)) as countBuilt,
COUNT(SWITCH(tblHist.ActionType <>1 OR tblHist.ActionType <>2 OR ...,1)) as countLost
FROM ..
WHERE ....
GROUP BY tblHist.ActionDate