Access substitute for EXCEPT clause - sql

How can I get the same result I would get with the SQL code below in ms access? It does not recognize the EXCEPT clause...
SELECT DISTINCT
P.Name,
T.Training
FROM Prof AS P,
Training_done AS TC,
Trainings AS T
WHERE (P.Name Like '*' & NameProf & '*')
AND (P.Primary_Area = T.Cod_Area)
EXCEPT
SELECT DISTINCT
P.Name,
T.Training
FROM Prof AS P,
Training_done AS TC,
Trainings AS T
WHERE (P.Name Like '*' & NameProf & '*')
AND (P.Cod_Prof = TC.Cod_Prof);
Thanks in advance!

In order to get rid of the EXCEPT you could combine the conditions and negate the second one:
SELECT DISTINCT
P.Name,
T.Training
FROM Prof AS P,
Training_done AS TC,
Trainings AS T
WHERE ((P.Name Like '*' & NameProf & '*') AND
(P.Primary_Area = T.Cod_Area))
AND NOT ((P.Name Like '*' & NameProf & '*') AND
(P.Cod_Prof = TC.Cod_Prof));

SELECT A.x FROM A
EXCEPT
SELECT B.x FROM B
corresponds to
SELECT A.x FROM A
LEFT JOIN B
ON A.x = B.x
WHERE B.x IS NULL

use the find unmatched wizard in MS Access > Create > Query Wizard and you will get the following result
Union is a separate Access Query which i used to union a few tables instead of using sub queries
SELECT TableMain.Field1
FROM TableMain LEFT JOIN [Union] ON TableMain.[Field1] = Union.[field1]
WHERE (((Union.field1) Is Null));

Not an explicit example here, but consider UNION-ing the two fetched tables and selecting, from that union, pairs that have fewer than 2 instances of a certain field combination. This implies that, where each table has more than one instance of a record with the same values on the field combination, these records are the same and can be eliminated from result set. Where not, they are unique to one table, leaving fetch with only records from the selected table where there is no match to the other table. Kind of like a poor-man's "EXCEPT" KW.

Related

Python unpacking operator / unpack subquery in separated columns

In Python there is the unpacking operator (*), which allows you to take an iterator or iterable (tuple, list, generator, etc.) and pass each of its items as an argument to a function. I want to do the same thing with a Postgresql subquery. But I can't find any information anywhere.
I want to do something like this:
INSERT INTO tabla1(a, b, c) SELECT a, *(SELECT b, c FROM tabla2 LIMIT 1) FROM tabla3
To avoid doing two almost identical selects and speed up my queries.
I want to AVOID something like this:
INSERT INTO tabla1(a, b, c) SELECT a, (SELECT b FROM tabla2 LIMIT 1), (SELECT c FROM tabla2 LIMIT 1) FROM tabla3
I tried the following:
review documentation
use with statement (It doesn't work for me because I can't relate a query column to the subquery, which would be necessary for me)
Read a question from this site (I don't have the link)
My question would be, is there something similar to that in Postgresql or any way to affect multiple columns with a single subquery? For example, something like the with statement with which you can do name_of_the_query.column?
Edit
This is the query I did with with, the test query with real names, I hope it makes my question better quality.
WITH ztabla02 AS (SELECT (CASE WHEN LEFT(maecuent.cuenta, 1) IN ('1','2','3') THEN
array[(SELECT descripcio FROM ztabla02 WHERE c_tabla='PR' AND c_clave=maecuent.cod_pcia), 'ARGENTINA']
ELSE
array['', (SELECT descripcio FROM ztabla02 WHERE c_tabla='PA' AND c_clave=maecuent.cod_pcia)]
END)
AS tuple)
SELECT ztabla02.tuple[1], ztabla02.tuple[2] FROM maecuent
Error:
ERROR: falta una entrada para la tabla «maecuent» en la cláusula FROM
LINE 1: WITH ztabla02 AS (SELECT (CASE WHEN LEFT(maecuent.cuenta, 1)...
^
You can do it with a CTE
with t2 as (
SELECT b, c FROM tabla2 LIMIT 1
)
INSERT INTO tabla1(a, b, c)
SELECT t3.a, t2.b, t2.c
FROM tabla3 t3
CROSS JOIN t2
Note LIMIT without ORDER BY will return an arbitrary row.

List of words in A -> Query: When *word* in record (Table B), then populate xxx (Table B) with corresponding record of Table A

I use MS Access SQL.
I have two tables. TableA is like a dictionary (like word1 - groupe_one, word3 - group_two)
I want to create a Query in which all data of TableB is included, but also if the record belongs to any group, which is defined in TableA.
The only solution I found is not using a TabeA but instead use:
SWITCH(TableB.sentence like '*word1*', 'group_one', '*word2*', 'group_one')
However this only works to a certain degree and is not very easy to handle.
You seem to want something like this:
select b.*, a.group
from tableB as b, tableA as a
where " " & b.sentence & " " like "* " & a.fragment & " *";
Notes:
MS Access is finicky about inequalities in the on clause, so this is phrased using a cross join (and MS Access doesn't support cross join.
The wildcard in MS Access is not the standard '%' but '*'.
This adds spaces before and after the word and sentence to get a "word" match.
You can join on a condition that uses LIKE:
SELECT tb.sentence, ta.group
FROM tableA ta
INNER JOIN tableB tb ON (tb.sentence LIKE ('*' & ta.fragment & '*'))

Can nested query in JPQL access outer query

So I'm curious if a nested SELECT can reference it's outer SELECT in order to compare values. I haven't been able to test or see many examples on this topic.
As an example, I'm trying to write a query to select all Clothes rows that has a tag (some number) that is within a given list and has the highest time that is prior to given time (which is total number of seconds). The query in question is below:
SELECT c FROM Clothes c WHERE c.tag IN :tagList
AND (c.timeOfSale = (SELECT MAX(n.timeOfSale) FROM Clothes k
WHERE (c.tag = k.tag) AND (k.timeOfSale) < (:time))) GROUP BY c.tag
Is the comparison c.tag = k.tag valid? If not, is there an alternative?
#Query("SELECT b FROM Business b WHERE b <> :currentBusiness "
+ "and exists "
+ "(Select i from InterestMaster i, BusinessInterest bI where bI.interestMaster = i and bI.business = b"
+ "and i in (:userInterests))")
Page<Business> getCommunityBusiness(#Param("currentBusiness") Business currentBusiness, #Param("userInterests") List<InterestMaster> userInterests,Pageable pageable);
I am using the above JPQL and its working fine. So yes nested query can access outer query.
Yes. They're called correlated queries, where the subquery is evaluated for each row of outer query.

How do I generate an Oracle SQL statement , where each column would need its own separate query?

I have a query where I need to use separate queries to fill in the individual columns :
It would look Something like this for each column
select PERFORMED_DATE from HHS_UMX_RESP_ACTIVITY where
REG_REQUEST_ID IN ('261507') AND ACTIVITY_RESULT_CODE = 'ASD'
AS "Security"
UNION
select PERFORMED_DATE from HHS_UMX_RESP_ACTIVITY where
REG_REQUEST_ID IN ('261507') AND ACTIVITY_RESULT_CODE = 'OTZ'
AS "Training"
UNION
select PERFORMED_DATE from HHS_UMX_RESP_ACTIVITY where
REG_REQUEST_ID IN ('261507') AND ACTIVITY_RESULT_CODE = 'ARA'
AS "Responsibility"
The only thing changing in each column is the ACTIVITY_RESULT_CODE.
I know that this syntax would not work. Is there a syntax to do this?
My query would grab different data from a specific table, for each different column.
My database output screenshot, which is for this query :
SELECT * FROM HHS_UMX_RESP_ACTIVITY where REG_REQUEST_ID IN ('262050') AND ACTIVITY_RESULT_CODE = 'ASD' AND ROWNUM < 2 :
The user-spreadsheet looks like this :
So columns "Responsibility" / "Supervisor" would each correspond to their own unique value for the column ACTIVITY_RESULT_CODE ( these called "UPA request statuses" - one of SBT, WSP, ASP, WRA, ARA, WTV, ATV ... etc ) :
thanks !
So you want to display information from different rows in the same row of the result set. The standard answer is a join, even if we join the same table:
select
securityRow.REQ_REQUEST_ID,
securityRow.PERFORMED_DATE as securityDate,
trainingRow.PERFORMED_DATE as trainingDate,
responsibilityRow.PERFORMED_DATE as responsibilityDate
from HHS_UMX_RESP_ACTIVITY securityRow
join HHS_UMX_RESP_ACTIVITY trainingRow on trainingRow.REG_REQUEST_ID = securityRow.REG_REQUEST_ID
join HHS_UMX_RESP_ACTIVITY responsibilityRow on responsibilityRow.REQ_REQUEST_ID = securityRow.REG_REQUEST_ID
where securityRow.ACTIVITY_RESULT_CODE = 'ASD'
and trainingRow.ACTIVITY_RESULT_CODE = 'OTZ'
and responsibilityRow.ACTIVITY_RESULT_CODE = 'ARA'
This assumes that there is exactly one row matching for each REQ_REQUEST_ID and ACTIVITY_RESULT_CODE. Otherwise, if there is at most one, you'll want to use outer joins as necessary. If there are several rows, you must restrict the result set to the one you want to use.
You say "For each different column" but there are not different columns. Only different selections on the Activity_result_code.
They syntax you have now, with the exception of the table aliases, would work fine, it's just completely unnecessary. The query you have written could also be written as:
select PERFORMED_DATE
from HHS_UMX_RESP_ACTIVITY
where REG_REQUEST_ID = '261507' AND ACTIVITY_RESULT_CODE IN ('ASD','OTZ','ARA');
GROUP BY PERFORMED_DATE

MS Access SQL: Enumerate results from a many-to-one relationship

Very simply, I have a many-to-one relationship table set in MS Access where I've managed to pull out the distinct values as separate rows. I now need to enumerate these rows.
The query looks like the following (generated by the MS Access Designer - apologies for the formatting):
SELECT DISTINCT ValidationRule.ValidationCode AS Rule, Table.Template AS Template
FROM ValidationRule RIGHT JOIN (([Table] INNER JOIN TableVersion ON Table.TableID = TableVersion.TableID) INNER JOIN ValidationScope ON TableVersion.TableVID = ValidationScope.TableVID) ON ValidationRule.ValidationId = ValidationScope.ValidationID
GROUP BY ValidationRule.ValidationCode, Table.Template
ORDER BY ValidationRule.ValidationCode;
So my data looks like:
Rule Template
v0007_m C 00.01
v0189_h C 01.00
v0189_h C 05.01
v3000_i C 08.00
I need to add sequential values to the results as follows:
Rule Template Sequence
v0007_m C 00.01 1
v0189_h C 01.00 1
v0189_h C 05.01 2
v3000_i C 08.00 1
What function should I be looking at in MS Access SQL to do this?
If you save the query you have as a separate query called qryValdationRule, this query which builds off that should give you what you need:
SELECT qryValidationRule.Rule, qryValidationRule.Template, DCount("*", 'qryValidationRule', "[Rule] = '" & qryValidationRule.Rule & "' AND [Template] <= '" & qryValidationRule.Template & "'") AS Sequence
FROM qryValidationRule
ORDER BY qryValidationRule.Rule, qryValidationRule.Template;
We are looking up and getting a count of all records with the same Rule value with an equal or less Template value within the dataset. This, essentially, gives us a Sequence grouped by Rule. This only works properly if Template values are distinct across Rule groups, which should be the case because you are pulling a DISTINCT across the CROSS JOIN of tables. It is not as convenient or flexible as window functions, but will get you what you need.
You may also want to try this method, which may be more efficient:
SELECT t1.Rule, t1.Template, COUNT(t2.Template) AS Sequence
FROM qryValidationRule AS t1 INNER JOIN qryValidationRule AS t2 ON t1.Rule = t2.Rule AND t1.Template >= t2.Template
GROUP BY t1.Rule, t1.Template
ORDER BY t1.Rule, t1.Template;
EDIT: Added an alternative way to find the same data; may be more performant because of JOINing vs. subqueries.
Use: Count(*) AS Sequence
SELECT DISTINCT ValidationRule.ValidationCode AS Rule, Table.Template AS Template, Count(*) AS Sequence
FROM ValidationRule RIGHT JOIN (([Table] INNER JOIN TableVersion ON Table.TableID = TableVersion.TableID) INNER JOIN ValidationScope ON TableVersion.TableVID = ValidationScope.TableVID) ON ValidationRule.ValidationId = ValidationScope.ValidationID
GROUP BY ValidationRule.ValidationCode, Table.Template
ORDER BY ValidationRule.ValidationCode;