Labels

admin (1) aix (1) alert (1) always-on (2) Architecture (1) aws (3) Azure (1) backup (3) BI-DWH (10) Binary (3) Boolean (1) C# (1) cache (1) casting (3) cdc (1) certificate (1) checks (1) cloud (3) cluster (1) cmd (7) collation (1) columns (1) compilation (1) configurations (7) Connection-String (2) connections (6) constraint (6) copypaste (2) cpu (2) csv (3) CTE (1) data-types (1) datetime (23) db (547) DB2 (1) deadlock (2) Denali (7) device (6) dotNet (5) dynamicSQL (11) email (5) encoding (1) encryption (4) errors (124) excel (1) ExecutionPlan (10) extended events (1) files (7) FIPS (1) foreign key (1) fragmentation (1) functions (1) GCP (2) gMSA (2) google (2) HADR (1) hashing (3) in-memory (1) index (3) indexedViews (2) insert (3) install (10) IO (1) isql (6) javascript (1) jobs (11) join (2) LDAP (2) LinkedServers (8) Linux (15) log (6) login (1) maintenance (3) mariadb (1) memory (4) merge (3) monitoring (4) MSA (2) mssql (444) mssql2005 (5) mssql2008R2 (20) mssql2012 (2) mysql (36) MySQL Shell (5) network (1) NoSQL (1) null (2) numeric (9) object-oriented (1) offline (1) openssl (1) Operating System (4) oracle (7) ORDBMS (1) ordering (2) Outer Apply (1) Outlook (1) page (1) parameters (2) partition (1) password (1) Performance (103) permissions (10) pivot (3) PLE (1) port (4) PostgreSQL (14) profiler (1) RDS (3) read (1) Replication (12) restore (4) root (1) RPO (1) RTO (1) SAP ASE (48) SAP RS (20) SCC (4) scema (1) script (8) security (10) segment (1) server (1) service broker (2) services (4) settings (75) SQL (74) SSAS (1) SSIS (19) SSL (8) SSMS (4) SSRS (6) storage (1) String (35) sybase (57) telnet (2) tempdb (1) Theory (2) tips (120) tools (3) training (1) transaction (6) trigger (2) Tuple (2) TVP (1) unix (8) users (3) vb.net (4) versioning (1) windows (14) xml (10) XSD (1) zip (1)

Or conditional join

The case:

SELECT ...
FROM TableA a
JOIN TableB b ON (a.ID = b.ID OR a.ID = b.ParentID)

or:
JOIN TableB b ON     a.ID = b.ID
                           AND    (b.AColumn = @AColumn OR @AColumn = 0)
                           -- @AColumn = 0 mean no condition ("all")


Of course it's not forbidden to use conditional join, 
but most of the time it won't be good to the performance of the query.
There are few possible solutions.

0. Keep use the conditional join

For cases the the performance are not get Worse (example: small tables),
or when the 'complecated' cases are uncommon.


1. UNION

Good for 'simple' cases:

Instead of:

SELECT ...
FROM TableA a
JOIN TableB b ON (a.ID = b.ID OR a.ID = b.ParentID)

use:

SELECT ...
FROM TableA a
JOIN TableB b ON a.ID = b.ID
UNION
SELECT ...
FROM TableA a
JOIN TableB b ON a.ID = b.ParentID

or similar case:
Instead of:

SELECT ...
FROM TableA a
JOIN TableB b ON     a.ID = b.ID
                           AND    (b.AColumn = a.AColumn OR b.BColumn = a.BColumn)

Use:
       SELECT ...
       FROM TableA a
       JOIN TableB b ON     a.ID = b.ID
                                  AND b.AColumn = a.AColumn
UNION
SELECT ...
FROM TableA a
JOIN TableB b ON     a.ID = b.ID
                           AND    b.BColumn = a.BColumn


2. filter in the "where":

Instead of:
SELECT ...
FROM TableA a
JOIN TableB b ON     a.ID = b.ID
                                  AND    (b.AColumn = @AColumn OR @AColumn = 0)

SELECT ...
FROM TableA a
JOIN TableB b ON     a.ID = b.ID
WHERE (b.AColumn = @AColumn OR @AColumn = 0))


3. 2 queries:

For cases that the JOIN is depended on a parameter:

Instead of:

SELECT ...
FROM TableA a
JOIN TableB b ON     a.ID = b.ID
                           AND    (b.AColumn = @AColumn OR @AColumn = 0)
                           -- @AColumn = 0 mean no condition ("all")
Use:
IF @AColumn = 0
       SELECT ...
       FROM TableA a
       JOIN TableB b ON     a.ID = b.ID
ELSE
SELECT ...
FROM TableA a
JOIN TableB b ON     a.ID = b.ID
                           AND    b.AColumn = @AColumn -- without consider the case of @AColumn = 0


4. Insert data to temp table

It's good for similar cases like in point 2, but for queries with a lot of joined tables
What we'll do is to store the data for the conditional join in a temp table and use it in the main query:

Instead of:

SELECT ...
FROM TableA a
JOIN TableB b ON     a.ID = b.ID
                           AND    (b.AColumn = @AColumn OR @AColumn = 0)
                           -- @AColumn = 0 mean no condition ("all")
JOIN TableC c .....
JOIN TableD d .....
JOIN TableE e .....

Use:

CREATE TABLE #TempCond (

INSERT INTO #TempCond ()
       SELECT ... -- take the relevant columns
       FROM TableA a
       JOIN TableB b ON     a.ID = b.ID
                                  AND    (b.AColumn = @AColumn OR @AColumn = 0)

--Or, if required, use one of the solutions in points 1,2 to this temp insertion
SELECT ...
FROM #TempCond
JOIN TableC c .....
JOIN TableD d .....
JOIN TableE e .....

No comments:

Post a Comment