Combine two different select statements, one distinct the other not - sql

I have two selects which are required to filter data. They are not complicated:
"SELECT * FROM StevesTable t WHERE "
"t.data1 = '%s' AND "
"t.data2 = to_date('%s','DD/MM/YYYY');",
strdata1,
dtDate.Format();
and
SELECT distinct data1 FROM anothertable ftt
join table1 tab on tab.somedata = ftt.somedata
where tab.somedata = 0
and tab.someotherdata = 1
I would like to combine these two as I need to filter the returned dataset from the first select statement by the returned field in the second (ie if a record returned in the first set does not have a data1 value which is contained in the second returned set it is invalid).
I tried to union and intersect the selects but you need the same number of columns returned and that cannot happen as these are completely different tables. When I tried to simply merge them together I found it difficult as the second select statement is a distinct select whereas the first is not.
I was wondering whether I had missed a trick somewhere for combining these sorts of selects?

What you need is a SQL sub-query:
SELECT * FROM StevesTable t
WHERE t.data1 = '%s'
AND t.data2 = to_date('%s','DD/MM/YYYY')
AND t.data1 in (select distinct data1 FROM anothertable ftt
join table1 tab on tab.somedata = ftt.somedata
where tab.somedata = 0
and tab.someotherdata = 1)
There, you check that all records in the first select have a data1 value in the second set.

You can do this using an EXISTS condition:
SELECT * FROM StevesTable t
WHERE t.data1 = '%s' AND
t.data2 = to_date('%s','DD/MM/YYYY') AND
EXISTS (select null
from anothertable ftt
join table1 tab on tab.somedata = ftt.somedata
where tab.somedata = 0 and
tab.someotherdata = 1 and
ftt.data1 = t.data1)

Related

SQL Why is my SELECT selecting duplicate rows?

This is a sub query:
SELECT t1.element_mark, t1.element_length, t1.element_width, t1.element_height, t1.product, t1.mass FROM IMP_ELEMENT as t1 WHERE TRIM(t1.project) = '99999';
This is the result:
This is my second sub query:
SELECT t2.element_id, t2.building, t2.floor_id, t2.deleted, t2.ELEMENT_MARK
FROM IMP_MODEL_GEOMETRY as t2
WHERE TRIM(t2.project) = '99999' AND TRIM(t2.building) = '1' AND TRIM(CAST(t2.floor_id AS VARCHAR(MAX))) = '1' AND t2.deleted = 0
ORDER BY t2.ELEMENT_MARK;
This is the result:
Now i'd like to combine them:
SELECT t1.element_mark, t1.element_length, t1.element_width, t1.element_height, t1.product, t1.mass, t2.element_id, t2.building, t2.floor_id, t2.deleted
FROM IMP_ELEMENT as t1
LEFT JOIN IMP_MODEL_GEOMETRY as t2 ON t1.element_mark = t2.element_mark
WHERE TRIM(t2.project) = '99999' AND TRIM(t2.building) = '1' AND TRIM(CAST(t2.floor_id AS VARCHAR(MAX))) = '1' AND t2.deleted = 0
ORDER BY t2.element_id;
And this is the result:
So what do i want?
I want only one result per "element_id".
I first want to SELECT"element_id" and then i want to find a match in the second table. To find a match i will use "element_mark". What is wrong in my query? why do i get multiple element_id?
As suggested by one of the comments, you probably have missed the WHERE clause in the first table. Try this query instead:
SELECT
t1.element_mark, t1.element_length, t1.element_width, t1.element_height, t1.product, t1.mass, t2.element_id, t2.building, t2.floor_id, t2.deleted
FROM
IMP_ELEMENT as t1
LEFT JOIN
IMP_MODEL_GEOMETRY as t2
ON
t1.element_mark = t2.element_mark
WHERE
TRIM(t2.project) = '99999' AND
TRIM(t2.building) = '1' AND
TRIM(CAST(t2.floor_id AS VARCHAR(MAX))) = '1' AND
t2.deleted = 0 AND
TRIM(t1.project) = '99999'
ORDER BY t2.element_id;
When joining two tables, in your case with a left join, if there are multiple matches on the join condition, multiple rows will be in the result set. You are joining based on element_mark- so for the first record of the first query- 3 rows will be returned in your result. What I would suggest is put the second table at the left part of the query or do a RIGHT JOIN. This way, because element_mark looks unique in the first table, you will get one record per element_id.
If you want to keep all elements and get matching information -- if any -- from the second table, then you want the LEFT JOIN. However, all conditions on the second table need to be in the ON clause:
SELECT t1.element_mark, t1.element_length, t1.element_width, t1.element_height, t1.product, t1.mass,
t2.element_id, t2.building, t2.floor_id, t2.deleted
FROM IMP_ELEMENT t1 LEFT JOIN
IMP_MODEL_GEOMETRY t2
ON t1.element_mark = t2.element_mark AND
TRIM(t2.project) = '99999' AND
TRIM(t2.building) = '1' AND
TRIM(CAST(t2.floor_id AS VARCHAR(MAX))) = '1' AND
t2.deleted = 0
ORDER BY t2.element_id;
There is no WHERE clause because all the filters are on the second table.

How to write a query to get data count with combination of codision

I have two tables named [DrugPrescriptionEdition] and [PrescriptionDoseDetail] and now, I join that two tables using the below query and taking a result set.
select * from DrugPrescription dp where id in(
SELECT distinct dpe.template
FROM [DrugPrescriptionEdition] dpe
join PrescriptionDoseDetail pdd on pdd.prescription = dpe.id
where doseEnd_endDate is NULL and doseEnd_doseEndType =1
)
but now I want to take records only contain, (1,2) combination of 'datasource' column and prescription.id should be same.
Example : like records { prescriptionID =4 and there contain ,(1,2) }. I will not consider, only 1 ,or 2 contain records.
Need some expert help to adding this conditions to my above query and modify it .
Expected result : I need to filter out , above query result using this, new condition too.
Let me assume your records are in a single table. Here is one method:
select t.*
from t
where (t.dataSource = 1 and
exists (select 1
from t t2
where t2. prescriptionid = t.prescriptionid and
t2.dataSource = 2
)
) or
(t.dataSource = 2 and
exists (select 1
from t t2
where t2.prescriptionid = t.prescriptionid and
t2.dataSource = 2
)
);
It is unclear if any other data sources are allowed. If they are not, then add:
and
not exists (select 1
from t t3
where t3.prescriptionid = t.prescriptionid and
t3.dataSource not in (1, 2)
)

Ms Access query to SQL Server - DistinctRow

What would the syntax be to convert this MS Access query to run in SQL Server as it doesn't have a DistinctRow keyword
UPDATE DISTINCTROW [MyTable]
INNER JOIN [AnotherTable] ON ([MyTable].J5BINB = [AnotherTable].GKBINB)
AND ([MyTable].J5BHNB = [AnotherTable].GKBHNB)
AND ([MyTable].J5BDCD = [AnotherTable].GKBDCD)
SET [AnotherTable].TessereCorso = [MyTable].[J5F7NR];
DISTINCTROW [MyTable] removes duplicate MyTable entries from the results. Example:
select distinctrow items
items.item_number, items.name
from items
join orders on orders.item_id = items.id;
In spite of the join getting you the same item_number and name multiple times when there is more than one order for it, DISTINCTROW reduces this to one row per item. So the whole join is merely for assuring that you only select items for which exist at least one order. You don't find DISTINCTROW in any other DBMS as far as I know. Probably because it is not needed. When checking for existence, we use EXISTS of course (or IN for that matter).
You are joining MyTable and AnotherTable and expect for some reason to get the same MyTable record multifold for one AnotherTable record, so you use DISTINCTROW to only get it once. Your query would (hopefully) fail if you got two different MyTable records for one AnotherTable record.
What the update does is:
update anothertable
set tesserecorso = (select top 1 j5f7nr from mytable where mytable.j5binb = anothertable.gkbinb and ...)
where exists (select * from mytable where mytable.j5binb = anothertable.gkbinb and ...)
But this uses about the same subquery twice. So we'd want to update from a query instead.
The easiest way to get one result record per <some columns> in a standard SQL query is to aggregate data:
select *
from anothertable a
join
(
select j5binb, j5bhnb, j5bdcd, max(j5f7nr) as j5f7nr
from mytable
group by j5binb, j5bhnb, j5bdcd
) m on m.j5binb = a.gkbinb and m.j5bhnb = a.gkbhnb and m.j5bdcd = a.gkbdcd;
How to write an updateble query is different from one DBMS to another. Here is the final update statement for SQL-Server:
update a
set a.tesserecorso = m.j5f7nr
from anothertable a
join
(
select j5binb, j5bhnb, j5bdcd, max(j5f7nr) as j5f7nr
from mytable
group by j5binb, j5bhnb, j5bdcd
) m on m.j5binb = a.gkbinb and m.j5bhnb = a.gkbhnb and m.j5bdcd = a.gkbdcd;
The DISTINCTROW predicate in MS Access SQL removes duplicates across all fields of a table in join statements and not just the selected fields of query (which DISTINCT in practically all SQL dialects do). So consider selecting all fields in a derived table with DISTINCT predicate:
UPDATE [AnotherTable]
SET [AnotherTable].TessereCorso = main.[J5F7NR]
FROM
(SELECT DISTINCT m.* FROM [MyTable] m) As main
INNER JOIN [AnotherTable]
ON (main.J5BINB = [AnotherTable].GKBINB)
AND (main.J5BHNB = [AnotherTable].GKBHNB)
AND (main.J5BDCD = [AnotherTable].GKBDCD)
Another variant of the query.. (Too lazy to get the original tables).
But like the query above updates 35 rows =, so does this one
UPDATE [Albi-Anagrafe-Associati]
SET
[Albi-Anagrafe-Associati].CRegDitte = [055- Registri ditte].[CRegDitte],
[Albi-Anagrafe-Associati].NIscrTribunale = [055- Registri ditte].[NIscrTribunale],
[Albi-Anagrafe-Associati].NRegImprese = [055- Registri ditte].[NRegImprese]
FROM [055- Registri ditte]
WHERE EXISTS(
SELECT *
FROM [055- Registri ditte]-- [Albi-Anagrafe-Associati]
WHERE ([055- Registri ditte].GIBINB = [Albi-Anagrafe-Associati].GKBINB)
AND ([055- Registri ditte].GIBHNB = [Albi-Anagrafe-Associati].GKBHNB)
AND ([055- Registri ditte].GIBDCD = [Albi-Anagrafe-Associati].GKBDCD))
Update [AnotherTable]
Set [AnotherTable].TessereCorso = MyTable.[J5F7NR]
From [AnotherTable]
Inner Join
(
Select Distinct [J5BINB],[5BHNB],[J5BDCD]
,(Select Top 1 [J5F7NR] From MyTable) as [J5F7NR]
,[J5BHNB]
From MyTable
)as MyTable
On (MyTable.J5BINB = [AnotherTable].GKBINB)
AND (MyTable.J5BHNB = [AnotherTable].GKBHNB)
AND (MyTable.J5BDCD = [AnotherTable].GKBDCD)

Want to get only 1 record back from an inner join that can pass back multiple records

I have the following SQL query:
SELECT *
FROM My_TABL wr
INNER JOIN His_TABL pk ON (wr.Company = pk.company AND wr.NUMBER = pk.number)
WHERE wr.NUMBER = 'L00499233'
AND wr.S_CODE IN ('in', 'ji', 'je')
I want to get back 1 record but found out that it can pass back multiple records because a record could have more than 1 field with 'in', 'ji' and 'je'
How can I just pick the first one? Thanks.
If the goal is to join to the top 1 match on the join (ultimately returning several rows), use an OUTER APPLY:
SELECT *
FROM My_TABL wr
OUTER APPLY ( SELECT TOP 1 * FROM His_TABL pk WHERE wr.Company = pk.company
AND wr.NUMBER = pk.number ) AS pk2
WHERE wr.NUMBER = 'L00499233'
AND wr.S_CODE IN ( 'in', 'ji', 'je' );
However, if the goal is to return only a single row in your result set, use Stuart's suggestion.
If it doesn't matter which row you want, you can use TOP 1:
select TOP 1 * from My_TABL wr
inner join His_TABL pk on (wr.Company = pk.company and wr.NUMBER = pk.number)
where wr.NUMBER = 'L00499233' and wr.S_CODE in ('in', 'ji', 'je')
Note that you should get out of the habit of using SELECT * and be more precise about the rows and columns you want to retrieve.

WHERE NOT EXISTS multiple conditions

How Do I set multiple AND conditions?
ex.
SELECT *
FROM CONFIRMED
WHERE NOT EXISTS
(
SELECT *
FROM Import_Orders
WHERE Import_Orders.Customer = CONFIRMED.Customer
AND Import_Orders.Reference = CONFIRMED.Reference
AND Import_Orders.[Index] = CONFIRMED.[Index]
AND Import_Orders.QuantityToDeliver = CONFIRMED.QuantityToDeliver
AND Import_Orders.DateToDeliver = CONFIRMED.DateToDeliver
);
I know this works on my tables with one WHERE & AND condition but not with several.
I Need a result of two tables where the above conditions do not match. I do not have identical keys in the two tables. Now with this code I get all the results that are in table CONFIRMED.
Here is the syntax for multiple tables:
WHERE NOT EXISTS (...) AND NOT EXISTS (...) AND NOT EXISTS (...)
However, if the database is so large that you care about performance, you'll need a much less obvious syntax along the following lines:
LEFT JOIN Some_Table t ON (t.xxx = Main_Table.xxx)
LEFT JOIN Another_Table t2 ON (t2.xxx = Main_Table.xxx)
LEFT JOIN Yet_Another_Table t3 ON (t3.xxx = Main_Table.xxx)
...
WHERE t.id IS NULL AND t2.id IS NULL AND t3.id IS NULL
For one table and one composed condition, like in the SQL sample in your question:
LEFT JOIN Some_Table t ON
t.xxx = Main_Table.xxx
AND t.yyy = Main_Table.yyy
AND t.zzz = Main_Table.zzz
WHERE t.id IS NULL
This is expected to return rows that exist in Main_Table but do not have matching rows in Some_Table, assuming the columns xxx, etc., are non-nullable.
If, for example, xxx is nullable, here is how you need to modify the query further:
LEFT JOIN Some_Table t ON
(t.xxx = Main_Table.xxx OR (t.xxx IS NULL AND Main_Table.xxx IS NULL))
AND t.yyy = Main_Table.yyy
AND t.zzz = Main_Table.zzz
WHERE t.id IS NULL
I am guessing that you have an ID on Import_Orders, if not use any field name that is turning up empty on the query. You would be better using field names rather than *. I have added an example for Import_Orders.
SELECT CONFIRMED.*, Import_Orders.ID, Import_Orders.Customer
FROM CONFIRMED
LEFT JOIN Import_Orders
ON Import_Orders.Customer = CONFIRMED.Customer
AND Import_Orders.Reference = CONFIRMED.Reference
AND Import_Orders.[Index] = CONFIRMED.[Index]
AND Import_Orders.QuantityToDeliver = CONFIRMED.QuantityToDeliver
AND Import_Orders.DateToDeliver = CONFIRMED.DateToDeliver
WHERE Import_Orders.ID Is Null
More information
Fundamental Microsoft Jet SQL for Access 2000
Intermediate Microsoft Jet SQL for Access 2000
Advanced Microsoft Jet SQL for Access 2000
You could just replace all the "=" with "<>" and you should get all the results that don't have a match on all criteria.
SELECT *
FROM CONFIRMED
WHERE EXISTS
(
SELECT *
FROM Import_Orders
WHERE Import_Orders.Customer <> CONFIRMED.Customer
AND Import_Orders.Reference <> CONFIRMED.Reference
AND Import_Orders.[Index] <> CONFIRMED.[Index]
AND Import_Orders.QuantityToDeliver <> CONFIRMED.QuantityToDeliver
AND Import_Orders.DateToDeliver <> CONFIRMED.DateToDeliver
);