converting sql server query to oracle outer join issue - sql-server

We had the following query in sql server:
SELECT b.columnB,
b.displayed_name AS displayName,
c.type_cd,
c.type_desc,
b.month_desc AS month
FROM table1 a, table2 b, table3 c
WHERE b.region_code *= a.columnA
AND c.program_type_cd *= a.program_type_cd
which, in oracle, got converted to:
SELECT b.columnB,
b.displayed_name displayName,
c.type_cd,
c.type_desc,
b.month_desc month
FROM table1 a,
table2 b,
table3 c
WHERE b.columnB = a.columnA(+)
AND c.type_cd = a.type_cd(+)
But while running this in oracle we get an error
"a table must be outer joined to at most one other table"
whats the best way to fix this and keep the same logic as sql server?

Try this once:
SELECT b.columnB,
b.displayed_name displayName,
c.type_cd,
c.type_desc,
b.month_desc month
FROM table1 a
LEFT JOIN table2 b ON b.columnB = a.columnA
LEFT JOIN tablec c ON c.type_cd = a.type_cd

Why is table1 listed as an OUTER JOIN if you're not returning any data from it? It seems like you'd want table1 to be an inner join to table2, and then do an OUTER between 2 and 3. Like this:
SELECT b.columnB,
b.displayed_name displayName,
c.type_cd,
c.type_desc,
b.month_desc month
FROM table1 a,
table2 b,
table3 c
WHERE b.columnB = a.columnA
AND c.type_cd = a.type_cd(+)
On another note, I'd recommond switching to ANSI joins (as in Eric's example) - they're much easier to read, though functionally, they're the same thing and are executed the exact same way.

Related

Display common values in two tables that are not present in the third table

The three tables in question are:
Table A - relevant columns are TimeTicket and IdAddress
Table B - relevant columns are CommunicationNumber, TimeCreate and IdAddress.
Table C - relevant columns are CommunicationNumber, LastCalled, NextCall
Table C is created by a join of TableA and TableB on IdAddress
INSERT INTO tblC ([CommunicationNumber], [LastCalled] ,[NextCall])
SELECT T2.CommunicationNumber, T2.TimeCreate, T1.TimeTicket
FROM tblA T1
INNER JOIN tblB T2
ON T1.IdAddress = T2.IdAddress AND T2.CommunicationNumber IS NOT NULL
That's one part of the process, and that's fine.
Now, when there is new data in Table A and Table B, I want to update the data entries in Table C. However, I want to ignore the values from Table A and Table B that I have already entered into Table C.
To achieve this, I used NOT EXISTS and wrote a query that looks like this.
INSERT INTO tblC ([CommunicationNumber], [LastCalled] ,[NextCall])
SELECT T2.CommunicationNumber, T2.TimeCreate, T1.TimeTicket
FROM tblA T1
INNER JOIN tblB T2
ON T1.IdAddress = T2.IdAddress AND T2.CommunicationNumber IS NOT NULL
WHERE NOT EXISTS (SELECT T3.CommunicationNumber
FROM [dbo].[tblPhoneLogRep] T3
WHERE T1.TimeTicket <> T3.NextCall AND T2.TimeCreate <> T3.LastCalled AND T2.CommunicationNumber <> T3.CommunicationNumber)
However, this query always returns an empty set.
Could someone please explain to me what is it that I am doing incorrectly?
Try using the EXCEPT set operator:
INSERT INTO tblC ([CommunicationNumber], [LastCalled] ,[NextCall])
SELECT T2.CommunicationNumber, T2.TimeCreate, T1.TimeTicket
FROM tblA T1
INNER JOIN tblB T2
ON T1.IdAddress = T2.IdAddress AND T2.CommunicationNumber IS NOT NULL
EXCEPT
SELECT CommunicationNumber, LastCalled, NextCall FROM tblC
To fix your existing query, you would need to change your <> operators to = operators, like so:
INSERT INTO tblC ([CommunicationNumber], [LastCalled] ,[NextCall])
SELECT T2.CommunicationNumber, T2.TimeCreate, T1.TimeTicket
FROM tblA T1
INNER JOIN tblB T2
ON T1.IdAddress = T2.IdAddress AND T2.CommunicationNumber IS NOT NULL
WHERE NOT EXISTS (SELECT 1
FROM tblC
WHERE T1.TimeTicket = tblC.NextCall AND T2.TimeCreate = tblC.LastCalled AND T2.CommunicationNumber = tblC.CommunicationNumber)
Personally, I think the EXCEPT syntax is more clear though.
Your issue is that you are essentially using a double negative. You are saying NOT EXISTS and you are setting your WHERE criteria to <>. I think it would work out if you either used EXISTS or change you criteria =.

Referencing Results of Multiple Temporary Tables in SQL Server

I’m using SQL Server 2008
I have joins written something like the following, where the first join is encapsulated in a ‘With as’ statement so that I can name the output table as ‘A’ and then reference the ‘A’ resulting table in the next select and Join seen beneath it.
This works perfectly fine. What I would like to do then is reference that second table for another select statement and join, but when I try to wrap it in a ‘With as’ statement as well, the editor does not accept it as legitimate syntax for the second instance of 'With as'.
How can I subset resulting tables to reference in further select and join statements? I do not have permission to write to the database, so I can not create permanent tables in the database.
Thank you.
With A as
(
SELECT POL.[COMPANY_CODE]
,POL.[POLICY_NUMBER]
,POL.[STATUS_CODE]
,POL.ORIG_CLIENT_NUM
,TA.LINE
FROM [SamsReporting].[dbo].[POLICY] POL
Left join [SamsReporting].[dbo].[Transact] TA
ON TA.POLICY_NUMBER = POL.POLICY_NUMBER and TA.BASE_Account = 'B'
)
Select PM.POLICY_NUMBER
,A.[COMPANY_CODE]
,A.[POLICY_NUMBER]
,A.[Policy Status]
,eApp.SourceCode
From A
Left Join Web.dbo.Pmetrics PM on A.POLICY_NUMBER=PM.POLICY_NUMBER
Left Outer Join DDP.pol.eAppStaging eApp
on A.POLICY_NUMBER=eApp.PolicyNumber
where eApp.SourceCode = 'HAQ' or eApp.SourceCode = 'PLS'
Common Table Expressions (CTEs) can build upon each other as you would like. For example, you can do this:
WITH CTE1 AS (SELECT * FROM Table 1)
, CTE2 AS (SELECT * FROM CTE1)
, CTE3 AS (SELECT * FROM CTE2)
You only need the WITH statement for the first CTE. After that just use the CTE name, as in my example.
Hope that helps,
Ash
Sounds like a syntax issue to me. Google CTE (Common Table Expression) and review some examples of how they are formed.
With A as
(SELECT POL.[COMPANY_CODE]
,POL.[POLICY_NUMBER]
,POL.[STATUS_CODE]
,POL.ORIG_CLIENT_NUM
,TA.LINE
FROM [SamsReporting].[dbo].[POLICY] POL
Left join [SamsReporting].[dbo].[Transact] TA
ON TA.POLICY_NUMBER = POL.POLICY_NUMBER and TA.BASE_Account = 'B'),
B as (
Select PM.POLICY_NUMBER
,A.[COMPANY_CODE]
,A.[POLICY_NUMBER]
,A.[Policy Status]
,eApp.SourceCode
From A
Left Join Web.dbo.Pmetrics PM on A.POLICY_NUMBER=PM.POLICY_NUMBER
Left Outer Join DDP.pol.eAppStaging eApp
on A.POLICY_NUMBER=eApp.PolicyNumber
where eApp.SourceCode = 'HAQ' or eApp.SourceCode = 'PLS')
Select *
From B -- inner join some table
where some condition = 1

SQL Server date_format in join

I have two tables with two formats date
table 1 :
id time ref
5 1397635972 A
10 1397635975 B
50 1397635976 C
table 2 :
id time ref
10 2013/10/05 D
51 2014/01/02 E
how join two table on table1.id=table2.id and table1.time=table2.time
This is my attempt :
$sql=' select table1.id, table1.time, table1.ref, table2.id, table2.time, table2.ref
from table1 INNER JOIN table2
ON (table1.id = table2.id AND DATE_FORMAT(table1.time,'%y/%m/%d') = table2.time)';
Try this:
select table1.id, table1.time, table1.ref, table2.id, table2.time, table2.ref
from table1 INNER JOIN table2
ON (table1.id = table2.id AND FROM_UNIXTIME(table1.time) = table2.time)
Are you sure that the ID needs to be a part of the join as well? This kind of join with this kind of structure would make almost no sense from a database design standpoint...
No data are not shown
For example FROM_UNIXTIME table2.time :
SELECT FROM_UNIXTIME(1196440219) : '2007-11-30 10:30:19'
I need to format then become : 2013/10/05

Get a collision free hash for a specific query or a view with SQL Server 2008

I am working on a project where I need to synchronize data from our system to an external system. What I want to achieve, is to periodically send only changed items (rows) from a custom query. This query looks like this (but with many more columns) :
SELECT T1.field1,
T1.field2,
T1.field2,
T1.field3,
CASE WHEN T1.field4 = 'some-value' THEN 1 ELSE 0 END,
T2.field1,
T3.field1,
T4.field1
FROM T1
INNER JOIN T2 ON T2.pk = T2.fk
INNER JOIN T3 ON T3.pk = T2.fk
INNER JOIN T4 ON T4.pk = T2.fk
I want to avoid to have to compare every field one to one between synchronizations. I came with the idea that I could generate a hash for every row from my query, and compare this with the hash from the previous synchronization, which will return only the changed rows. I am aware of the CHECKSUM function, but it is very collision-prone and might miss changes sometimes. However I like the way I could just make a temp table and use CHECKSUM(*), which makes maintenance easier (not having to add fields in the query and in the CHECKSUM) :
SELECT T1.field1,
T1.field2,
T1.field2,
T1.field3,
CASE WHEN T1.field4 = 'some-value' THEN 1 ELSE 0 END,
T2.field1,
T3.field1,
T4.field1
INTO #tmp
FROM T1
INNER JOIN T2 ON T2.pk = T2.fk
INNER JOIN T3 ON T3.pk = T2.fk
INNER JOIN T4 ON T4.pk = T2.fk;
-- get all columns from the query, plus a hash of the row
SELECT *, CHECKSUM(*)
FROM #tmp;
I am aware of HASHBYTES function (which supports sha1, md5, which are less prone to collisions), but it only accept varchar or varbinary, not a list of columns or * the way CHECKSUM does. Having to cast/convert every column from the query is a pain in the ... and opens the door to errors (forget to include a new field for instance)
I also noticed Change Data Capture and Change Tracking features of SQL Server, but they all seems complicated and overkill for what I am doing.
So my question : is there an other method to generate a hash from a query or a temp table that meets my criterias ?
If not, is there an other way to achieve this kind of work (to sync differences from a query)
I found a way to do exactly what I wanted, thanks to the FOR XML clause :
SELECT T1.field1,
T1.field2,
T1.field2,
T1.field3,
CASE WHEN T1.field4 = 'some-value' THEN 1 ELSE 0 END,
T2.field1,
T3.field1,
T4.field1
INTO #tmp
FROM T1
INNER JOIN T2 ON T2.pk = T2.fk
INNER JOIN T3 ON T3.pk = T2.fk
INNER JOIN T4 ON T4.pk = T2.fk;
-- get all columns from the query, plus a hash of the row (converted in an hex string)
SELECT T.*, CONVERT(VARCHAR(100), HASHBYTES('sha1', (SELECT T.* FOR XML RAW)), 2) AS sHash
FROM #tmp AS T;

How to Merge SQL Query(Help required)

Dear friends, below are my two SQL queries:
select distinct
a_bm.DestProvider_ID,
a_bm.DestCircel_ID,
convert(datetime,dbo.fnToDate(a_bm.BM_BillFrom),103) as fromdate,
convert(datetime,dbo.fnToDate(a_bm.BM_BillTo),103) as todate,
t_rec.TapInRec as BillRecevable,
t_rec.TapInRec as Billreceied
from Auditdata_BillingMaster a_bm
inner join TapInRecordMaster t_rec
on a_bm.DestProvider_ID = t_rec.DestProviderMaster_ID
and a_bm.DestCircel_ID = t_rec.DestCircelMaster_ID
and convert(datetime,dbo.fnToDate(a_bm.BM_BillFrom),103)> =
convert(datetime,t_rec.Months)
and convert(datetime,dbo.fnToDate(a_bm.BM_BillTo),103)<=
convert(datetime,t_rec.BillTo)
where a_bm.DestProvider_ID=4
and a_bm.DestCircel_ID=22
and a_bm.typeoffile=1
and convert(datetime,dbo.fnToDate(a_bm.BM_BillFrom),103)>=
convert(datetime,'6/1/2009')
and convert(datetime,dbo.fnToDate(a_bm.BM_BillFrom),103)<=
convert(datetime,'7/30/2009')
select Temp_tbl.fromdate from Temp_tbl Temp_tbl
inner join (
select
convert(datetime,dbo.fnToDate(BM_BillFrom),103) as a1,
convert(datetime,dbo.fnToDate(BM_BillTo),103) as b1,
count(*) as c1,
am_bm.DestProvider_ID,
am_bm.DestCircel_ID
from Auditdata_BillingMaster am_bm
inner join Temp_tbl tmp
on tmp.Provider_ID=am_bm.DestProvider_ID
and tmp.Circel_ID=am_bm.DestCircel_ID
where convert(datetime,tmp.fromdate)>=
convert(datetime,dbo.fnToDate(am_bm.BM_BillFrom),103)
and convert(datetime,tmp.todate) <=
convert(datetime,dbo.fnToDate(am_bm.BM_BillTo),103)
group by
convert(datetime,dbo.fnToDate(BM_BillFrom),103),
convert(datetime,dbo.fnToDate(BM_BillTo),103),
am_bm.DestProvider_ID,
am_bm.DestCircel_ID
) b
on Temp_tbl.Provider_ID = b.DestProvider_ID
and Temp_tbl.Circel_ID = b.DestCircel_ID
and convert(datetime,Temp_tbl.fromdate,101)>= convert(datetime,(b.a1),101)
and convert(datetime,Temp_tbl.todate) <= convert(datetime,(b.b1),101)
I want to merge above 2 SQL query in SQL Server 2000.
Please help me.
Thanks in advance.
Do you mean to JOIN or UNION both tables?
If you mean to JOIN both query results, simply take both results as input for JOIN statement.
How you join both results is really dependent on your database design. Preferably the join is based on referential integrity enforcing the relationship between the results to ensure data integrity. But since you do not mention the join condition, let me assume you will join based on DestProvider_ID & DestCircel_ID.
select
result1.DestProvider_ID,
result1.DestCircel_ID,
result1.fromdate,
result1.todate,
result1.BillRecevable,
result1.Billreceied,
result2.fromdate
from
( *your first query* ) as result1
inner join
(select
Temp_tbl.fromdate,
am_bm.DestProvider_ID,
am_bm.DestCircel_ID
from Temp_tbl Temp_tbl
*the rest of your second query*
) as result2 on result1.DestProvider_ID = result2.DestProvider_ID
and result1.DestCircel_ID = result2.DestCircel_ID
UNION:
If you want to take multiple select statements and combine them into one result set, UNION statement is the easiest way to go:
SELECT column1a, column2a, column3a FROM tableA
UNION
SELECT column1b, column2b, column3b FROM tableB
This is possible only if:
both queries have same number of columns
Corresponding columns in each query expression must be of the same data type
data type of column1a == column1b
data type of column2a == column2b
data type of column3a == column3b
Since both of your queries do not have same number of columns, you can't merge them, at least with UNION select.

Resources