By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
434,826 Members | 2,384 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 434,826 IT Pros & Developers. It's quick & easy.

Query: union on self

P: n/a
Hello every body.

I have a small issue.

Problem: I have a table with 4 descriptor columns (type). I need to
formulate a query to retrieve a count for each type so I can group
by...etc. The view I have works, but doesn't work when I supplement the
query with some functions... they just don't like the UNION. The real
problem is I can't change any of the udf's or queries, just the view.
The view is inner joined back on to the primary table 'qt_ins' again
and a heap of other tables. But for this post and to not complicate it
too much I've just included the primary table and the view...
Also my querys work if I don't put a where clause on for the VIEW. eg:
.... and cv.type = 'Environmental'.... for some reason with a clause it
gets stuck in an *infinite loop.
Conditions: The table structure cannot be changed in anyway. The
view/query must return 2 columns qi_id & type.

I considered creating a function to return the Types but then I figured
I would ask you folks for a better way.

Any help with the view appreciated.

Thank you.

The below will create the table, with sample data and the view.

---------------------------Start
Query--------------------------------------------
CREATE TABLE [dbo].[qt_ins] (
[qi_id] [int] NOT NULL ,
[qi_injury] [bit] NULL ,
[qi_environmental] [bit] NULL ,
[qi_equipment_damage] [bit] NULL ,
[qi_vehicle] [bit] NULL
) ON [PRIMARY]
GO

INSERT INTO qt_ins
(qi_id,qi_injury,qi_environmental,qi_equipment_dam age,qi_vehicle)
VALUES (20,1,0,0,0)
INSERT INTO qt_ins
(qi_id,qi_injury,qi_environmental,qi_equipment_dam age,qi_vehicle)
VALUES (21,0,1,0,0)
INSERT INTO qt_ins
(qi_id,qi_injury,qi_environmental,qi_equipment_dam age,qi_vehicle)
VALUES (23,1,0,0,0)
INSERT INTO qt_ins
(qi_id,qi_injury,qi_environmental,qi_equipment_dam age,qi_vehicle)
VALUES (24,1,0,0,0)
INSERT INTO qt_ins
(qi_id,qi_injury,qi_environmental,qi_equipment_dam age,qi_vehicle)
VALUES (25,1,1,1,1)
INSERT INTO qt_ins
(qi_id,qi_injury,qi_environmental,qi_equipment_dam age,qi_vehicle)
VALUES (26,1,0,0,0)
INSERT INTO qt_ins
(qi_id,qi_injury,qi_environmental,qi_equipment_dam age,qi_vehicle)
VALUES (27,1,0,0,0)
INSERT INTO qt_ins
(qi_id,qi_injury,qi_environmental,qi_equipment_dam age,qi_vehicle)
VALUES (28,1,0,0,0)
INSERT INTO qt_ins
(qi_id,qi_injury,qi_environmental,qi_equipment_dam age,qi_vehicle)
VALUES (29,1,0,0,0)
INSERT INTO qt_ins
(qi_id,qi_injury,qi_environmental,qi_equipment_dam age,qi_vehicle)
VALUES (30,1,1,1,1)
INSERT INTO qt_ins
(qi_id,qi_injury,qi_environmental,qi_equipment_dam age,qi_vehicle)
VALUES (31,1,0,0,0)
INSERT INTO qt_ins
(qi_id,qi_injury,qi_environmental,qi_equipment_dam age,qi_vehicle)
VALUES (32,1,1,1,0)
INSERT INTO qt_ins
(qi_id,qi_injury,qi_environmental,qi_equipment_dam age,qi_vehicle)
VALUES (33,1,0,0,0)
INSERT INTO qt_ins
(qi_id,qi_injury,qi_environmental,qi_equipment_dam age,qi_vehicle)
VALUES (34,1,1,1,0)
INSERT INTO qt_ins
(qi_id,qi_injury,qi_environmental,qi_equipment_dam age,qi_vehicle)
VALUES (35,1,0,0,1)
INSERT INTO qt_ins
(qi_id,qi_injury,qi_environmental,qi_equipment_dam age,qi_vehicle)
VALUES (36,1,0,0,0)
INSERT INTO qt_ins
(qi_id,qi_injury,qi_environmental,qi_equipment_dam age,qi_vehicle)
VALUES (37,0,0,0,1)
INSERT INTO qt_ins
(qi_id,qi_injury,qi_environmental,qi_equipment_dam age,qi_vehicle)
VALUES (38,0,0,0,1)
INSERT INTO qt_ins
(qi_id,qi_injury,qi_environmental,qi_equipment_dam age,qi_vehicle)
VALUES (39,0,1,0,0)
INSERT INTO qt_ins
(qi_id,qi_injury,qi_environmental,qi_equipment_dam age,qi_vehicle)
VALUES (40,1,0,0,0)
INSERT INTO qt_ins
(qi_id,qi_injury,qi_environmental,qi_equipment_dam age,qi_vehicle)
VALUES (41,0,0,0,0)
INSERT INTO qt_ins
(qi_id,qi_injury,qi_environmental,qi_equipment_dam age,qi_vehicle)
VALUES (42,1,0,0,0)
INSERT INTO qt_ins
(qi_id,qi_injury,qi_environmental,qi_equipment_dam age,qi_vehicle)
VALUES (43,1,0,0,0)
INSERT INTO qt_ins
(qi_id,qi_injury,qi_environmental,qi_equipment_dam age,qi_vehicle)
VALUES (44,0,1,1,0)
INSERT INTO qt_ins
(qi_id,qi_injury,qi_environmental,qi_equipment_dam age,qi_vehicle)
VALUES (45,1,0,0,0)
INSERT INTO qt_ins
(qi_id,qi_injury,qi_environmental,qi_equipment_dam age,qi_vehicle)
VALUES (46,1,0,0,0)
INSERT INTO qt_ins
(qi_id,qi_injury,qi_environmental,qi_equipment_dam age,qi_vehicle)
VALUES (47,1,0,0,0)
INSERT INTO qt_ins
(qi_id,qi_injury,qi_environmental,qi_equipment_dam age,qi_vehicle)
VALUES (48,1,0,0,0)
INSERT INTO qt_ins
(qi_id,qi_injury,qi_environmental,qi_equipment_dam age,qi_vehicle)
VALUES (49,1,0,0,0)
INSERT INTO qt_ins
(qi_id,qi_injury,qi_environmental,qi_equipment_dam age,qi_vehicle)
VALUES (50,1,0,1,0)
INSERT INTO qt_ins
(qi_id,qi_injury,qi_environmental,qi_equipment_dam age,qi_vehicle)
VALUES (51,0,0,1,0)
INSERT INTO qt_ins
(qi_id,qi_injury,qi_environmental,qi_equipment_dam age,qi_vehicle)
VALUES (52,0,1,0,0)
INSERT INTO qt_ins
(qi_id,qi_injury,qi_environmental,qi_equipment_dam age,qi_vehicle)
VALUES (53,1,0,0,0)
INSERT INTO qt_ins
(qi_id,qi_injury,qi_environmental,qi_equipment_dam age,qi_vehicle)
VALUES (54,1,0,0,0)
INSERT INTO qt_ins
(qi_id,qi_injury,qi_environmental,qi_equipment_dam age,qi_vehicle)
VALUES (55,1,0,0,0)
INSERT INTO qt_ins
(qi_id,qi_injury,qi_environmental,qi_equipment_dam age,qi_vehicle)
VALUES (56,1,1,1,1)
INSERT INTO qt_ins
(qi_id,qi_injury,qi_environmental,qi_equipment_dam age,qi_vehicle)
VALUES (57,1,0,0,0)
INSERT INTO qt_ins
(qi_id,qi_injury,qi_environmental,qi_equipment_dam age,qi_vehicle)
VALUES (58,1,0,0,0)
INSERT INTO qt_ins
(qi_id,qi_injury,qi_environmental,qi_equipment_dam age,qi_vehicle)
VALUES (59,0,1,0,0)
INSERT INTO qt_ins
(qi_id,qi_injury,qi_environmental,qi_equipment_dam age,qi_vehicle)
VALUES (60,0,1,0,0)
INSERT INTO qt_ins
(qi_id,qi_injury,qi_environmental,qi_equipment_dam age,qi_vehicle)
VALUES (61,1,0,0,0)
INSERT INTO qt_ins
(qi_id,qi_injury,qi_environmental,qi_equipment_dam age,qi_vehicle)
VALUES (62,0,1,0,0)
INSERT INTO qt_ins
(qi_id,qi_injury,qi_environmental,qi_equipment_dam age,qi_vehicle)
VALUES (63,1,0,0,0)
INSERT INTO qt_ins
(qi_id,qi_injury,qi_environmental,qi_equipment_dam age,qi_vehicle)
VALUES (64,1,0,0,0)
INSERT INTO qt_ins
(qi_id,qi_injury,qi_environmental,qi_equipment_dam age,qi_vehicle)
VALUES (65,1,0,1,0)
INSERT INTO qt_ins
(qi_id,qi_injury,qi_environmental,qi_equipment_dam age,qi_vehicle)
VALUES (66,1,0,0,1)
INSERT INTO qt_ins
(qi_id,qi_injury,qi_environmental,qi_equipment_dam age,qi_vehicle)
VALUES (67,1,1,1,1)
INSERT INTO qt_ins
(qi_id,qi_injury,qi_environmental,qi_equipment_dam age,qi_vehicle)
VALUES (68,1,0,0,0)
INSERT INTO qt_ins
(qi_id,qi_injury,qi_environmental,qi_equipment_dam age,qi_vehicle)
VALUES (69,1,0,0,0)
INSERT INTO qt_ins
(qi_id,qi_injury,qi_environmental,qi_equipment_dam age,qi_vehicle)
VALUES (70,1,1,1,1)
INSERT INTO qt_ins
(qi_id,qi_injury,qi_environmental,qi_equipment_dam age,qi_vehicle)
VALUES (71,1,1,1,1)
INSERT INTO qt_ins
(qi_id,qi_injury,qi_environmental,qi_equipment_dam age,qi_vehicle)
VALUES (72,1,1,1,1)
INSERT INTO qt_ins
(qi_id,qi_injury,qi_environmental,qi_equipment_dam age,qi_vehicle)
VALUES (73,0,0,1,0)
INSERT INTO qt_ins
(qi_id,qi_injury,qi_environmental,qi_equipment_dam age,qi_vehicle)
VALUES (81,1,0,0,0)
GO
CREATE VIEW dbo.v_qt_in_type
AS
SELECT qi_id, 'Injury' AS type FROM qt_ins WHERE qi_injury = 1
UNION all
SELECT qi_id, 'Environmental' AS type FROM qt_ins WHERE
qi_environmental = 1
UNION all
SELECT qi_id, 'Equipment damage' AS type FROM qt_ins WHERE
qi_equipment_damage = 1
UNION all
SELECT qi_id, 'Vehicle' AS type FROM qt_ins WHERE qi_vehicle = 1
GO

select count(*),type from v_qt_in_type group by type
---------------------------END
QUERY--------------------------------------

Jul 10 '06 #1
Share this Question
Share on Google+
7 Replies


P: n/a
KoliPoki (ra****@gmail.com) writes:
Problem: I have a table with 4 descriptor columns (type). I need to
formulate a query to retrieve a count for each type so I can group
by...etc. The view I have works, but doesn't work when I supplement the
query with some functions... they just don't like the UNION. The real
problem is I can't change any of the udf's or queries, just the view.
The view is inner joined back on to the primary table 'qt_ins' again
and a heap of other tables. But for this post and to not complicate it
too much I've just included the primary table and the view...
Also my querys work if I don't put a where clause on for the VIEW. eg:
... and cv.type = 'Environmental'.... for some reason with a clause it
gets stuck in an *infinite loop.
I'm afraid that it's impossible to assist with the information you have
given. First you say "don't like the UNION", which indicates that you
have some trivial syntax error. Then you talk about infinite loops,
which indicates that the query runs for a very long time.

You posted a repro, which is great. Unfortunately, that repro appears to
work without any problems. If you instead post a repro that demonstrates
the problem, it's a lot easier to say what is going on.

--
Erland Sommarskog, SQL Server MVP, es****@sommarskog.se

Books Online for SQL Server 2005 at
http://www.microsoft.com/technet/pro...ads/books.mspx
Books Online for SQL Server 2000 at
http://www.microsoft.com/sql/prodinf...ons/books.mspx
Jul 10 '06 #2

P: n/a
Erland, thank you for your reply.

That's correct the UNION doesn't work with my query.
Unfortunately it's very hard to give you all the code as there are 3
functions and another 12 tables, 2 with hierarchical
(parent/child/lineage) data (Business units, Job titles).

There are no syntax errors, the problem is that my query never
returns... like it's stuck in a loop. If I remove the union like:
-----------------------------------------------
CREATE VIEW dbo.v_qt_in_type
AS
SELECT qi_id, 'Environmental' AS type FROM qt_ins WHERE
qi_environmental = 1
-------------------------------------------------
it works fine and fast, but is obviously incorrect as it only returns
records of 1 type.
So the problem is....

Can any one think of another way to write the below query without the
UNION

---------------Query to write in a different way---------------

SELECT qi_id, 'Injury' AS type FROM qt_ins WHERE qi_injury = 1
UNION all
SELECT qi_id, 'Environmental' AS type FROM qt_ins WHERE
qi_environmental = 1
UNION all
SELECT qi_id, 'Equipment damage' AS type FROM qt_ins WHERE
qi_equipment_damage = 1
UNION all
SELECT qi_id, 'Vehicle' AS type FROM qt_ins WHERE qi_vehicle = 1

------------------------END QUERY-------------------------------------

Thanks for your help, and apologies for not being able to provider the
full context of the issue.

R.

Erland Sommarskog wrote:
KoliPoki (ra****@gmail.com) writes:
Problem: I have a table with 4 descriptor columns (type). I need to
formulate a query to retrieve a count for each type so I can group
by...etc. The view I have works, but doesn't work when I supplement the
query with some functions... they just don't like the UNION. The real
problem is I can't change any of the udf's or queries, just the view.
The view is inner joined back on to the primary table 'qt_ins' again
and a heap of other tables. But for this post and to not complicate it
too much I've just included the primary table and the view...
Also my querys work if I don't put a where clause on for the VIEW. eg:
... and cv.type = 'Environmental'.... for some reason with a clause it
gets stuck in an *infinite loop.

I'm afraid that it's impossible to assist with the information you have
given. First you say "don't like the UNION", which indicates that you
have some trivial syntax error. Then you talk about infinite loops,
which indicates that the query runs for a very long time.

You posted a repro, which is great. Unfortunately, that repro appears to
work without any problems. If you instead post a repro that demonstrates
the problem, it's a lot easier to say what is going on.

--
Erland Sommarskog, SQL Server MVP, es****@sommarskog.se

Books Online for SQL Server 2005 at
http://www.microsoft.com/technet/pro...ads/books.mspx
Books Online for SQL Server 2000 at
http://www.microsoft.com/sql/prodinf...ons/books.mspx
Jul 10 '06 #3

P: n/a
You can try something like this:

SELECT qi_id,
case
when qi_injury = 1 then 'Injury'
when qi_environmental = 1 then 'environmental'
when qi_Equipment damage = 1 then 'Equipment damage'
when qi_Vehicle = 1 then 'Vehicle'
end
AS type
FROM qt_ins
WHERE (qi_injury = 1) or (qi_environmental = 1 ) or
(qi_equipment_damage = 1)
or (qi_vehicle = 1)

But it would be interesting to see why is your original query slow. Any
additional infotrmation?

Jul 11 '06 #4

P: n/a
KoliPoki wrote:
Erland, thank you for your reply.

That's correct the UNION doesn't work with my query.
Unfortunately it's very hard to give you all the code as there are 3
functions and another 12 tables, 2 with hierarchical
(parent/child/lineage) data (Business units, Job titles).

There are no syntax errors, the problem is that my query never
returns... like it's stuck in a loop. If I remove the union like:
-----------------------------------------------
CREATE VIEW dbo.v_qt_in_type
AS
SELECT qi_id, 'Environmental' AS type FROM qt_ins WHERE
qi_environmental = 1
-------------------------------------------------
it works fine and fast, but is obviously incorrect as it only returns
records of 1 type.
So the problem is....

Can any one think of another way to write the below query without the
UNION

---------------Query to write in a different way---------------

SELECT qi_id, 'Injury' AS type FROM qt_ins WHERE qi_injury = 1
UNION all
SELECT qi_id, 'Environmental' AS type FROM qt_ins WHERE
qi_environmental = 1
UNION all
SELECT qi_id, 'Equipment damage' AS type FROM qt_ins WHERE
qi_equipment_damage = 1
UNION all
SELECT qi_id, 'Vehicle' AS type FROM qt_ins WHERE qi_vehicle = 1

------------------------END QUERY-------------------------------------

Thanks for your help, and apologies for not being able to provider the
full context of the issue.
Alexander has given what I think is a pretty good solution to this. To
the original problem though, did you get a query plan for the select
statement that ran for so long? What was the query plan doing?

One thing to keep in mind is that if you are using UDFs, they can often
dramatically impact a querie's performance. It's impossible to know
without your data and the full table, UDF, and view SQL code, but maybe
when you use the UNION with the UDF it has to actually select the
entire dataset, applying the UDF to each row and then performing the
UNION operations before it is able to filter out rows based on your
WHERE clause criteria. I'm afraid that I don't know how smart SQL
Server is when you do a union like this within a view and then select
from the view based on a column that is calculated within the view.
Even if the UDF has nothing to do with it, it may be that when you
select WHERE qi_environmental = 1 then SQL Server can use an index, but
when you have a column hard-coded the way that you do in the unions it
can no longer use that index when you do WHERE type = 'Environmental'.

Anyway, just some stuff to look into for you.

-Tom.

Jul 11 '06 #5

P: n/a
Alexander Kuznetsov wrote:
You can try something like this:

SELECT qi_id,
case
when qi_injury = 1 then 'Injury'
when qi_environmental = 1 then 'environmental'
when qi_Equipment damage = 1 then 'Equipment damage'
when qi_Vehicle = 1 then 'Vehicle'
end
AS type
FROM qt_ins
WHERE (qi_injury = 1) or (qi_environmental = 1 ) or
(qi_equipment_damage = 1)
or (qi_vehicle = 1)

But it would be interesting to see why is your original query slow. Any
additional infotrmation?
I just posted that this was a good solution in another post, but now it
occurs to me that it will not return the same resultset as the original
poster's solution. The query above will return only one row per qi_id,
but the original solution could return up to four for each qi_id.

-Tom.

Jul 11 '06 #6

P: n/a
Thomas,

thanks for the correction. Untested again, no DDL, no DML!

SELECT qi_id, t.c AS type
FROM qt_ins join
(
select 1 n, 'Injury' c
union all
select 2 n, 'environmental' c
union all
select 3 n, 'Equipment damage' c
union all
select 4 n, 'Vehicle' c
) t
on (qi_injury = 1 and t.n=1) or (qi_environmental = 1 and t.n=2) or
(qi_equipment_damage = 1 and t.n=3)
or (qi_vehicle = 1 and t.n=4)

Jul 11 '06 #7

P: n/a
Thanks Folks.

I was dubious of using a derived table, as I had already tried wrapping
some of the logic in derived table and it didn't work, but I never
tried using a derived table for the view...guess what, it work!

Why, I'm still not sure.

The query was never returning when the view and a function were used in
the clause of the query.

Example of not working:
select qi_id, .....
from qt_ins q
inner join v_qt_in_type v on q.qu_id = v.qi_id
inner join ...
inner join ...
....
where
..... and
q.qi_mr_emp_no in(select emp_no from udf_qi_my_subordinates('49549'))
and
q.qi_observation_date>=dateadd(yy,-1,current_timestamp) and
v.type = 'Environmental' and
dbo.udf_qi_em_return_above_reportsto2_1(q.qi_mr_em p_no,'49549') = 'GM
OH&S'
But would return if either
dbo.udf_qi_em_return_above_reportsto2_1(q.qi_mr_em p_no,'49549') = 'GM
OH&S' or v.type = 'Environmental' was removed it would work even if
they were referenced the select string.

Example working:
select qi_id, .....
from qt_ins q
inner join v_qt_in_type v on q.qu_id = v.qi_id
inner join ...
inner join ...
....
where
..... and
q.qi_mr_emp_no in(select emp_no from udf_qi_my_subordinates('49549'))
and
q.qi_observation_date>=dateadd(yy,-1,current_timestamp) and
--v.type = 'Environmental' and
dbo.udf_qi_em_return_above_reportsto2_1(q.qi_mr_em p_no,'49549') = 'GM
OH&S'

Thanks Alexander for your help.
Alexander Kuznetsov wrote:
Thomas,

thanks for the correction. Untested again, no DDL, no DML!

SELECT qi_id, t.c AS type
FROM qt_ins join
(
select 1 n, 'Injury' c
union all
select 2 n, 'environmental' c
union all
select 3 n, 'Equipment damage' c
union all
select 4 n, 'Vehicle' c
) t
on (qi_injury = 1 and t.n=1) or (qi_environmental = 1 and t.n=2) or
(qi_equipment_damage = 1 and t.n=3)
or (qi_vehicle = 1 and t.n=4)
Jul 12 '06 #8

This discussion thread is closed

Replies have been disabled for this discussion.