views:

299

answers:

4

I don't like having the same thing defined in two places, if I can avoid it.

I realize the two queries below are dealing with two different tables, but those tables hold basically the same kind of data (distinct predicates warrant the two queries), and I think of the two projections below as "the same thing defined in two places".

When/if I modify these queries later, to include different columns, I'm sure I'll always want the projections to remain identical.

Given that, and without using dynamic SQL, and without '*' in any projection (not permitted in my production environment), can I define the "columnset" once and use it in both queries?

SELECT columnA
 , columnB
 , columnC
FROM Data

SELECT columnA
 , columnB
 , columnC
FROM DataArchive
A: 

I can't think of any efficient way of doing so. You could of course make a view with a UNION ALL of the two tables with the addition of a column that holds the table name as a string, then do SELECT columnA, columnB, columnC FROM view WHERE table = 'Data' but that feels like a rather ugly hack.

Blixt
+1  A: 

Have your base be a union of Data and DataArchive and use an inline table-valued function (SQL Server 2005 and up)?

CREATE FUNCTION UnifiedData (@LiveOnly bit, @ArchiveOnly bit)
RETURNS TABLE
AS
RETURN (
    SELECT columnA
           ,columnB
           ,columnC
    FROM (
        SELECT 'Live' AS Src, * 
        FROM Data
        WHERE @ArchiveOnly = 0

        UNION ALL

        SELECT 'Archive' AS Src, *
        FROM DataArchive
        WHERE @LiveOnly = 0
    )
)

Not great, but should be handled pretty well by the optimizer since it's inlined.

Cade Roux
I like it. I've now added the '*' prohibition to the question. My apologies for not including it originally.
lance
The * here is relatively harmless, since it is internal and not exposed. It also should be immune to changes in Data and Data Archive which could cause it to break unless they stop having the same schema. Normally I don't advocate its use except where justified.
Cade Roux
Small quibble, but wouldn't UNION ALL be more appropriate?
Peter
Yes, I will update the answer
Cade Roux
I failed to mention in my question that Data and DataArchive have different schemas. That aside, I like this answer very much. Thank you to everyone for the answers.
lance
A: 

Yeah, SQL is awful this way. There is no all-around satisfactory way to do it. Here's an example using synonyms:

if object_id('DataSynonym') is not null drop synonym DataSynonym
create synonym DataSynonym for Data
select columnA, columnB, columnC from DataSynonym

if object_id('DataSynonym') is not null drop synonym DataSynonym
create synonym DataSynonym for DataArchive
select columnA, columnB, columnC from DataSynonym

The issue with using synonyms this way is that they are global in scope. If you redefine a synonym on the fly in one connection, it will affect users on all other connections.

Temporary views/functions or view/function variables would go a long way to fix the problem. Or a macro language like what's available in SAS.

Peter
A: 

Create a view on Data UNION ALL DataArchive. If you are later able to to refactor and combine the 2 tables, this will be transparent to your existing queries.

orbfish