I'm having some trouble with a query to check differences between 2 identical tables with different rows.
This is the query
SELECT *
FROM [PROD01].[myDefDB].[forward].[fv] as DB01
WHERE TargetDate = '20150429' and
NOT EXISTS (SELECT *
FROM [PROD02].[myDefDB].[forward].[fv] as DB02
WHERE DB02.TargetDate = '20150429' and
DB02.Id_Fw = DB01.Id_Fw and
DB02.Id_Bl = DB01.Id_Bl and
DB02.Id_Pt = DB01.Id_Pt and
DB02.TargetDate = DB01.TargetDate and
DB02.StartDate = DB01.EndDate and
DB02.EndDate = DB01.EndDate and
DB02.[Version] = DB01.[Version]
)
Consider that [PROD02].[myDefDB].[forward].[fv] is a subset of [PROD01].[myDefDB].[forward].[fv], that performing a SELECT count(*) on both tables for the TargetDate = '20150429' returns me 2367 and 4103, so I expect to get 1736 from that query but I get more than 2000.
I considered all PKs in the WHERE clause. What am I missing?
You can use EXCEPT like this.
SELECT Id_Fw,Id_Bland,Id_Pt,TargetDate,StartDate,EndDate,[Version]
FROM [PROD01].[myDefDB].[forward].[fv] as DB01
WHERE TargetDate = '20150429'
EXCEPT
SELECT Id_Fw,Id_Bl,Id_Pt,TargetDate,StartDate,EndDate,[Version]
FROM [PROD02].[myDefDB].[forward].[fv] as DB02
WHERE TargetDate = '20150429'
This will get you all the rows in PROD01 which are not in PROD02
Related
I have an Oracle select that I need to execute in SQL Server (the table is exported from an Oracle database to a SQL Server database). I can replace nvl with isnull and decode with case I guess, but how to deal with the rowid in this specific case?
select sum(
nvl(
(select sum(b.restsaldo) from reskontro.erkrysskid b
where 1=1
and b.fakturanr = a.fakturanr
and b.kundenr = a.kundenr
and b.resknr = b.resknr
and a.rowid = decode(a.reskfunknr,31,a.rowid,b.rowid)
and nvl(b.restsaldo,0) <> 0
and b.krysskidid <= a.krysskidid
and not exists (select * from reskontro.erkrysskid c
where b.kundenr = c.kundenr
and b.resknr = c.resknr
and a.resklinr < c.resklinr
and a.krysskidid < c.krysskidid
and b.fakturanr = c.fakturanr
and c.reskfunknr in (31,75)
and nvl(c.attfort,-1) = -1)
),0
)
) as restsaldo from reskontro.erkrysskid a
where 1=1
and a.kundenr = 1
and a.resknr = 1
SQL Server doesn't have a ROWID pseudo column. In Oracle this is being used in the context of a self-join to determine if the two rows being joined are the same row. In SQL Server simply compare the table's key columns instead.
eg, if the table has a key on a Id column, use
and a.Id = case when a.reskfunknr = 31 then a.Id else b.Id end
My application uses a query that is working fine using a MySQL/MariaDB-Database.
I did modify my application to be more flexible and work with Microsoft SQL Server too.
Unfortunately the following query does NOT work using a SQL Server database:
select
p.PrinterGUID,
(exists (select 1
from computerdefaultprinter cdp
where cdp.PrinterGUID = p.PrinterGUID and
cdp.ComputerGUID = '5bec3779-b002-46ba-97c4-19158c13001f')
) as is_computer_default,
(exists (select 1
from userdefaultprinter udp
where udp.PrinterGUID = p.PrinterGUID and
udp.UserGUID = 'd3cf699b-8d71-4dbc-92f3-402950042054')
) as is_user_default
from
((select cm.PrinterGUID
from computermapping cm
where cm.ComputerGUID = '5bec3779-b002-46ba-97c4-19158c13001f'
) union -- to remove duplicates
(select PrinterGUID
from usermapping um
where um.UserGUID = 'd3cf699b-8d71-4dbc-92f3-402950042054')) p;
Running this query throws an error
Incorrect syntax near the keyword 'exists'
Microsoft SQL Server Management Studio returns the following in German:
I have created a SQL Fiddle with some example data: SQL-Fiddle
If necessary, more background-information is available here: UNION 2 Select-queries with computed columns
Is it possible to modify this query to work in both MySQL and SQL Server?
Thank you very much!
The literal translation of your query would be the following:
select
p.PrinterGUID,
CASE WHEN exists (select 1
from computerdefaultprinter cdp
where cdp.PrinterGUID = p.PrinterGUID and
cdp.ComputerGUID = '5bec3779-b002-46ba-97c4-19158c13001f')
THEN 1 ELSE 0 END as is_computer_default,
CASE WHEN exists (select 1
from userdefaultprinter udp
where udp.PrinterGUID = p.PrinterGUID and
udp.UserGUID = 'd3cf699b-8d71-4dbc-92f3-402950042054')
THEN 1 ELSE 0 END as is_user_default
from (select cm.PrinterGUID
from computermapping cm
where cm.ComputerGUID = '5bec3779-b002-46ba-97c4-19158c13001f'
union -- to remove duplicates
select PrinterGUID
from usermapping um
where um.UserGUID = 'd3cf699b-8d71-4dbc-92f3-402950042054') p;
Notice the use of a CASE expressions to determine the value of the column for when the EXISTS evaluates to true or not.
Just try out the following query. You don't need to use exists like this in sql server. Instead filter out the rows at the end using is_computer_default or is_user_default
select p.PrinterGUID,
(select 1
from computerdefaultprinter cdp
where cdp.PrinterGUID = p.PrinterGUID and
cdp.ComputerGUID = '5bec3779-b002-46ba-97c4-19158c13001f')
as is_computer_default,
(select 1
from userdefaultprinter udp
where udp.PrinterGUID = p.PrinterGUID AND
udp.UserGUID = 'd3cf699b-8d71-4dbc-92f3-402950042054'
) as is_user_default
from ((select cm.PrinterGUID
from computermapping cm
where cm.ComputerGUID = '5bec3779-b002-46ba-97c4-19158c13001f'
) union -- to remove duplicates
(select PrinterGUID
from usermapping um
where um.UserGUID = 'd3cf699b-8d71-4dbc-92f3-402950042054'
)
) p;
I'm comparing (one-way) two tables of different databases in SQL.
I want to update only the second table with the differences.
The comparing part gives me the correct results, but I have no clue how to get these result in the updating part
-- The comparing part DB1 with DB2
WITH RecordsWithUpdates AS
(SELECT DeviceID, DeviceName, DeviceNumber, Active FROM DB1.dbo.devices
EXCEPT
SELECT DeviceID, DeviceName, DeviceNumber, Active FROM DB2.dbo.devices
)
-- displaying the differences
Select * from DB2.dbo.Devices
WHERE DeviceID IN (SELECT DeviceID FROM RecordsWithUpdates)
-- Updating then columns of DB2
Update DB2.dbo.devices SET DeviceName = ?????, SET DeviceNumber = ??????, Active = ???????
The Code part with the ????? is where it should insert the found differences, but I cannot get it to work.
I would approach this with the UPDATE ... SET ... FROM ... JOIN syntax, like:
UPDATE
t2
SET
t2.DeviceName = t1.DeviceName,
t2.DeviceNumber = t1.DeviceNumber,
t2.Active = t1.Active
FROM
DB2.dbo.devices t2
INNER JOIN DB1.dbo.devices t1
ON t1.DeviceID = t2.DeviceID
AND NOT (
t1.DeviceName = t2.DeviceName
AND t1.DeviceNumber = t2.DeviceNumber
AND t1.Active = t2.Active
)
If you want at the same time to INSERT records that do not yet exists, then you can use the MERGE syntax instead:
MERGE DB2.dbo.devices t2
USING DB1.dbo.devices t1
ON (t1.DeviceID = t2.DeviceID)
WHEN MATCHED
THEN UPDATE SET
t2.DeviceName = t1.DeviceName,
t2.DeviceNumber = t1.DeviceNumber,
t2.Active = t1.Active
WHEN NOT MATCHED
THEN INSERT(DeviceID, DeviceName, DeviceNumber, Active)
VALUES (t1.DeviceID, t1.DeviceName, t1.DeviceNumber, t1.Active)
Finally: if you want to delete the records that exist in t2 but not in t1, just add this at the end of the MERGE query:
WHEN NOT MATCHED BY SOURCE
THEN DELETE;
Trying to exclude a set of values that meet the criteria from the query, but the query returns nothing.
select *
from rpt_StockInventorySummary a
where a.[DepartmentId] ='P'
and not exists (
select *
from rpt_StockInventorySummary b
where b.Manufacturer = 'warrington'
and b.LowestGroupDescription = 'Boots, Leather, 14 Inch, Pro'
and b.Instock = 0
and b.barcode = a.barcode
)
order by a.SortOrder
Edit
I think adding "and b.barcode = a.barcode" at the end of the query in the NOT EXISTS was what was missing.
What was missing from the query was this:
and b.barcode = a.barcode
Adding this to the query inside of the not exists did the trick.
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)