Showing posts with label complex. Show all posts
Showing posts with label complex. Show all posts

Sunday, March 11, 2012

Complicated query with really big tables

Dear Experts,

I want to write a very complex query on very huge tables.

The scenario is the following:

I have one table called #Products, one table called #Shops , one table called #Customers and one table called #CollectedInformation.

#Products (ProductID int, ProductName varchar(10))

Product Information. Around 70,000 unique products

#Shops(ShopID smallint, ShopName varchar(10))

Shop Information. Around 100 unique shops

#Customers(CustomerID smallint, CustomerName varchar(10)

Customer Information. Around 100 unique customers

#CollectedInformation(ProductID int, ShopID smallint, CustomerID int, SalesValue money)

Sales Information collected and inserted in a huge table. We don’t sell all products in all shops and to all customers. Maximum 70,000 products * 100 Shops * 100 customers, but usually it will contain around 650 million records instead of 700 million which is the max.

What I would like to get is for all products, fo all shops, for all customers to create a temporary table that will get SalesValue based on joining #Products, #Customers, #Shops with #CollectedInformation.

In case a product or customer or shop doesn’t have a value for field SalesValue I want it to appeear in the final table with Null as SalesValue.

To achieve this I used the CTE in SQL server 2005 to create a cartesian product between #Products, #Shops and #Customers and then I left outer join it with table #CollectedInformation.

(The cte command only with 70,000 products, 100 customers and only 2 - Out of 100 total shops takes around 1:20 minutes on a 2cpu 3.6GHz xeon 2GB Ram server connected with an HP MSA1000 SAN.)

Can you please help me to determine if there is a better way to do it. I Haven't tried it with the full set, but I believe it will be very slow.

Following is an example of the code I used for testing:

declare @.Customers int, @.Shops int, @.Products int

declare @.counter int

-- select @.Customers = 100, @.Shops = 100, @.Products =70000

--select @.Customers = 100, @.Shops = 2, @.Products =70000

select @.Customers = 100, @.Shops = 2, @.Products =700

create table #Customers(CustomerID smallint, CustomerName varchar(10))

set @.counter=1

while @.counter<=@.Customers

begin

insert into #Customers values(@.counter,'Cn'+str(@.counter,8))

set @.counter = @.counter +1

end

create unique clustered index C1 on #Customers(CustomerID)

create table #Shops(ShopID smallint, ShopName varchar(10))

set @.counter=1

while @.counter<=@.Shops

begin

insert into #Shops values((@.counter*2)+100, 's'+str(@.counter,9))

set @.counter = @.counter +1

end

create unique clustered index S1 on #Shops(ShopID)

create table #Products (ProductID int, ProductName varchar(10))

set @.counter=1

while @.counter<=@.Products

begin

insert into #Products values(@.counter,'p'+str(@.counter,9))

set @.counter = @.counter +1

end

create unique clustered index P1 on #Products(ProductID)

create table #CollectedInformation(ProductID int, ShopID smallint, CustomerID int, SalesValue money)

declare @.TempShopID int

declare Shops_cursor cursor fast_forward for

select ShopID

from #Shops

open Shops_cursor

fetch next from Shops_cursor

into @.TempShopID

while @.@.fetch_status = 0

begin

insert into #CollectedInformation (ShopID, ProductID, CustomerID)

select @.TempShopID, P.ProductID, C.CustomerID

from #Customers C, #Products P

fetch next from Shops_cursor

into @.TempShopID

end

close Shops_cursor

deallocate Shops_cursor

create clustered index ci1 on #CollectedInformation (CustomerID)

create index ci2 on #CollectedInformation (ProductID)

create index ci3 on #CollectedInformation (ShopID)

declare @.random money

set @.random = rand()

update #CollectedInformation

set SalesValue = cast((10000*@.random)+(ProductID*@.random)+(CustomerID*@.random)+(ShopID*@.random) as money)

-- Following is the code that creates the final temporary table:

declare @.PeriodNo int, @.Indicate char(1)

set @.PeriodNo =120

set @.Indicate='A';

with results_cte (ProductID, ProductName, ShopID, ShopName, CustomerID, CustomerName )

as

(

select p.ProductID, p.ProductName, s.ShopID, s.ShopName, c.CustomerID, c.CustomerName

from #Products p, #Shops s, #Customers c

)

select @.PeriodNo as Period , @.Indicate as SpecialSymbol, r.ProductID, r.ProductName, r.CustomerID, r.CustomerName, r.ShopID, r.ShopName, ci.Salesvalue

into #temp

from results_cte r

left outer join #CollectedInformation ci on ci.ProductID=r.ProductID and ci.ShopID=r.ShopID and ci.CustomerID=r.CustomerID

order by r.ProductID, r.CustomerID, r.ShopID

--select top 100 * from #temp

drop table #Products

drop table #Shops

drop table #Customers

drop table #CollectedInformation

drop table #temp

What are you trying to achieve in the end? How is the temporary table going to be used?

If you want to report on this can I suggest you look at analysis services.

In your code, what takes the time? Be aware that you don't have an index on the CollectedInformation table.

In addition when you scale up to 650 million rows. Assuming you have 4 integer fields in this table you will be processing 10Gb of data from 1 table. You are planning on joining two of these together thats 20Gb of data.

Any large processing of this nature is going to take time, reduced by having more processing power and more memory.

|||

Dear Simon,

The reason I need to create the temporary table is because I have to pass it through a CLR function which after a lot of processing, it will export data into a text file. (One line from the text file will consist of many rows from the #temp table - Shops will become columns on the text file - Every Product, every customer, salesvalueshop1, salesvalueshop2 etc. The CTE will be executed and processed by the CLR.)

Thanks for your advice on analysis services. I will take a look at it.

I have three indexes on the CollectedInformation

create clustered index ci1 on #CollectedInformation (CustomerID)

create index ci2 on #CollectedInformation (ProductID)

create index ci3 on #CollectedInformation (ShopID)

About the time and the size the table will contain at least: 1 int, 1 smallint, 3 tinyint, and 2 money fields(perhaps 1 can be reduced to smallmoney). The amount of data is per period. On the text file I may have up to 100 periods as well. I processed data period by period so that to reduce the size of the tables.

Actually I don't know if the cardesian product that the CTE creates which then left outer joins with CollectedInformation table is the best way. What i want from the query is to join collectedinformation with products, customers and shops. Some values from products, customers, shops will not be included on the collectedinformation table, but I want them to appear at the final text file with a * instead of the null value for thr collectedinformation.salesvalue (e.g. for one product, for one customer i have salesvalue for shop1 and shop2 only. text file: Product1, customer1, shop1salesvalue, shop2salesvalue, *, * No sales for shop 3 and 4)

Regards,

Spyros Christodoulou

complicated Join - duplicate row problem

Hi
I had a similar problem awhile back and it was solved here. Now it has
gotten more complex. I have removed uneeded stuff here to keep this
simple.:
I am sure I know why I am getting the results I am, but don't know
how (or if) there is a way around it. If someone can help, I will be
mighty excited and impressed !
Here goes:
Given a table definition:
CREATE TABLE table1
(col1 varchar(20),
col2 varchar(20),
col3 integer,
CONSTRAINT PK_table1 PRIMARY KEY (col1,col2))
and then (assuming table2 exists)
ALTER TABLE table1
ADD CONSTRAINT FK_table1_table2
FOREIGN KEY (col1)
REFERENCES table2 (col1)
REQUIREMENT:
I would like to select some schema information about this table. Among
other things, I want the column name, data type, and Primary Key and
Foreign Key information. For the Primary Key and Foreign Key, all I
need to know is if one or both of these attributes applies to a
column.
Therefore, I would like my result records to look like this:
name | type | PK_col | FK_col
--+--+--+--
col1 | varchar | PK | FK
col2 | varchar | PK |
col3 | integer | |
My problem is getting the PK and FK on the same row. My results are
currently like this:
name | type | PK_col | FK_col
--+--+--+--
col1 | varchar | PK |
col1 | varchar | | FK
col2 | varchar | PK |
col3 | integer | |
HERE IS THE QUERY:
SELECT cols.COLUMN_NAME as name,cols.DATA_TYPE as type,
PK_COL = case when T.CONSTRAINT_TYPE = 'PRIMARY KEY' then 'PK'
else '' END,
FK_Col = case when T.CONSTRAINT_TYPE = 'FOREIGN KEY' then 'FK'
else '' END
FROM Test.INFORMATION_SCHEMA.COLUMNS cols
left JOIN INFORMATION_SCHEMA.KEY_COLUMN_USAGE K
on cols.table_name = K.TABLE_NAME
and cols.column_name = K.column_name
left join INFORMATION_SCHEMA.TABLE_CONSTRAINTS T
on k.table_name = t.table_name
and K.CONSTRAINT_NAME = T.CONSTRAINT_NAME
and (T.CONSTRAINT_TYPE = 'PRIMARY KEY'
or T.CONSTRAINT_TYPE = 'FOREIGN KEY' or T.CONSTRAINT_TYPE = 'UNIQUE')
WHERE cols.TABLE_NAME = 'table1'
ORDER BY cols.ORDINAL_POSITION
So, Col1 is duplicated because there are two (2) entries (PK & FK) in
key_column_usage for that column.
Is there some way to combine these two result rows together taking the
PK info from 1 and the FK from the other?
Thanks
JeffHi, Jeff
Did you read my response to your previous post ?
http://groups.google.com/group/micr...br />
a2bf3ce9
It's exactly what you are requesting now...
Razvan|||Sorry, I had missed your earlier reply because it didn't show up in my
news reader under the question. I see it now. My mistake.
This looks good and makes sense.
Thank you very very much !!
Jeff
On 12 Jan 2006 23:28:37 -0800, "Razvan Socol" <rsocol@.gmail.com>
wrote:

>Hi, Jeff
>Did you read my response to your previous post ?
>http://groups.google.com/group/micr...r />
9a2bf3ce9
>It's exactly what you are requesting now...
>Razvan|||On Fri, 13 Jan 2006 06:38:33 GMT, Jeff User wrote:
(snip)
>Therefore, I would like my result records to look like this:
>name | type | PK_col | FK_col
>--+--+--+--
> col1 | varchar | PK | FK
> col2 | varchar | PK |
> col3 | integer | |
>My problem is getting the PK and FK on the same row. My results are
>currently like this:
>name | type | PK_col | FK_col
>--+--+--+--
> col1 | varchar | PK |
> col1 | varchar | | FK
> col2 | varchar | PK |
> col3 | integer | |
(snip)
Hi Jeff,
Just a few simple changes to the query should suffice:
SELECT cols.COLUMN_NAME as name,cols.DATA_TYPE as type,
PK_COL = MAX(case when T.CONSTRAINT_TYPE = 'PRIMARY KEY' then 'PK'
else '' END),
FK_Col = MAX(case when T.CONSTRAINT_TYPE = 'FOREIGN KEY' then 'FK'
else '' END)
FROM Test.INFORMATION_SCHEMA.COLUMNS cols
left JOIN INFORMATION_SCHEMA.KEY_COLUMN_USAGE K
on cols.table_name = K.TABLE_NAME
and cols.column_name = K.column_name
left join INFORMATION_SCHEMA.TABLE_CONSTRAINTS T
on k.table_name = t.table_name
and K.CONSTRAINT_NAME = T.CONSTRAINT_NAME
and (T.CONSTRAINT_TYPE = 'PRIMARY KEY'
or T.CONSTRAINT_TYPE = 'FOREIGN KEY' or T.CONSTRAINT_TYPE = 'UNIQUE')
WHERE cols.TABLE_NAME = 'table1'
ORDER BY cols.ORDINAL_POSITION
GROUP BY cols.COLUMN_NAME, cols.DATA_TYPE, cols.ORDINAL_POSITION
Hugo Kornelis, SQL Server MVP

Thursday, March 8, 2012

Complex(?) SQL Query

I need a complex query, but I will try to keep this short. I have four table
s
(call then Main, Building, Location and Unit). Main is the main table and ha
s
several fields. In Main, I have two fields that can reference Unit, and one
field that references Building. Unit also references Building, and Building
references Location
.
In other words, Units belong to a Building and a Building belongs to a
Location. If I have a Unit in Main, I have to go to Unit to get the Building
,
then Building to get the Building related info and the Location.
Table Main has a BuildingCode field and two UnitCode (UCa and UCb) fields.
If there is a UCa value, there should not be a BuildingCode and vice versa.
There may or may not be a value for UCb.
My query needs to return all related information in a single recordset (i.e.
Building.BuildingName & Location.LocationName based on a join from
BuildingCode in Main, and Unit.UnitName, Building.BuildingName and
Location.LocationName based on a join on UnitCode in Main (remember two
differnt places where UnitCode is used in Main and they can be different). I
f
this makes sense to anyone and they can help, I would be eternally grateful,
and if you are ever in the Kansas City are I will buy you dinner.
tia,
Dougdoug,
not sure if i understand completely, it would be much easier for all if you
posted some DDL and sample data.
do your tables look something like this?
create table locations (
location_code char(2) not null primary key,
location_name varchar(10) not null
)
go
create table buildings (
building_code char(2) not null primary key,
location_code char(2) not null foreign key references
locations(location_code),
building_name varchar(10) not null
)
go
create table units (
unit_code char(2) not null primary key,
building_code char(2) not null foreign key references
buildings(building_code),
unit_name varchar(10) not null
)
go
create table main (
main_code char(2) not null primary key,
unit_code_a char(2) null foreign key references units(unit_code),
unit_code_b char(2) null foreign key references units(unit_code),
building_code char(2) null foreign key references buildings(building_code),
check (case when unit_code_a is null then 0 else 1 end + case when
building_code is null then 0 else 1 end = 1)
)
go
and some sample data:
insert locations(location_code, location_name)
select 'L1', 'location 1'
union all
select 'L2', 'location 2'
insert buildings(building_code, location_code, building_name)
select 'B1', 'L1', 'building 1'
union all
select 'B2', 'L2', 'building 2'
insert units(unit_code, building_code, unit_name)
select 'U1', 'B1', 'unit 1'
insert main(main_code, unit_code_a, unit_code_b, building_code)
select 'M1', 'U1', null, null
union all
select 'M2', null, null, 'B2'
(it is unclear what is unit_code_b used for.. could you please explain?)
then we could do it like this:
select coalesce(b1.building_name,b2.building_name) as building_name,
coalesce(l1.location_name,l2.location_name) as location_name,
u.unit_name
from main m
left outer join units u on m.unit_code_a=u.unit_code and m.building_code is
null
left outer join buildings b1 on u.building_code=b1.building_code
left outer join locations l1 on b1.location_code=l1.location_code
left outer join buildings b2 on m.building_code=b2.building_code and
m.unit_code_a is null
left outer join locations l2 on b2.location_code=l2.location_code
dean
"Doug" <dbb211-hd204@.yahoo.com> wrote in message
news:08311DB6-A81A-4F73-924D-9A8F8143B125@.microsoft.com...
>I need a complex query, but I will try to keep this short. I have four
>tables
> (call then Main, Building, Location and Unit). Main is the main table and
> has
> several fields. In Main, I have two fields that can reference Unit, and
> one
> field that references Building. Unit also references Building, and
> Building
> references Location
> .
> In other words, Units belong to a Building and a Building belongs to a
> Location. If I have a Unit in Main, I have to go to Unit to get the
> Building,
> then Building to get the Building related info and the Location.
> Table Main has a BuildingCode field and two UnitCode (UCa and UCb) fields.
> If there is a UCa value, there should not be a BuildingCode and vice
> versa.
> There may or may not be a value for UCb.
> My query needs to return all related information in a single recordset
> (i.e.
> Building.BuildingName & Location.LocationName based on a join from
> BuildingCode in Main, and Unit.UnitName, Building.BuildingName and
> Location.LocationName based on a join on UnitCode in Main (remember two
> differnt places where UnitCode is used in Main and they can be different).
> If
> this makes sense to anyone and they can help, I would be eternally
> grateful,
> and if you are ever in the Kansas City are I will buy you dinner.
> tia,
> Doug|||Dean and others. Please see [url]http://www.cedar.cr.cc/images/relationship.jpg[/url
]
for a relationship diagram of the tables in question. A brief description of
why the relationships are as they are.
As you can probably tell, this is an inventory (of computers). A building
may or may not have units designated within it. If there are units in the
building, the unit field will be populated, otherwise the building field wil
l
be populated (in tblCIMComputers). The second Unit field is to allow
(usually) a person in another location to log into they system as though
their computer was located in a specific Unit (our login security system als
o
uses this table). As such, there may or may not be a value in this second
Unit field.
The reason for this type of layout is because Units can move from one
building to another. If such a move is made, one record in one table is
changed (i.e. BuildingCode in tblUnits) and all is well.
The constructs of the tables are very straight forward. Only field
definitions, primary and foreign keys. No other type of constraints. The
purpose of the query I am trying to build is to bring back all pertinent dat
a
to provide the person accessing it with a complete overview of all data.
"Dean" wrote:

> doug,
> not sure if i understand completely, it would be much easier for all if yo
u
> posted some DDL and sample data.
> do your tables look something like this?
> create table locations (
> location_code char(2) not null primary key,
> location_name varchar(10) not null
> )
> go
> create table buildings (
> building_code char(2) not null primary key,
> location_code char(2) not null foreign key references
> locations(location_code),
> building_name varchar(10) not null
> )
> go
> create table units (
> unit_code char(2) not null primary key,
> building_code char(2) not null foreign key references
> buildings(building_code),
> unit_name varchar(10) not null
> )
> go
> create table main (
> main_code char(2) not null primary key,
> unit_code_a char(2) null foreign key references units(unit_code),
> unit_code_b char(2) null foreign key references units(unit_code),
> building_code char(2) null foreign key references buildings(building_code)
,
> check (case when unit_code_a is null then 0 else 1 end + case when
> building_code is null then 0 else 1 end = 1)
> )
> go
>
> and some sample data:
> insert locations(location_code, location_name)
> select 'L1', 'location 1'
> union all
> select 'L2', 'location 2'
> insert buildings(building_code, location_code, building_name)
> select 'B1', 'L1', 'building 1'
> union all
> select 'B2', 'L2', 'building 2'
> insert units(unit_code, building_code, unit_name)
> select 'U1', 'B1', 'unit 1'
> insert main(main_code, unit_code_a, unit_code_b, building_code)
> select 'M1', 'U1', null, null
> union all
> select 'M2', null, null, 'B2'
> (it is unclear what is unit_code_b used for.. could you please explain?)
>
> then we could do it like this:
> select coalesce(b1.building_name,b2.building_name) as building_name,
> coalesce(l1.location_name,l2.location_name) as location_name,
> u.unit_name
> from main m
> left outer join units u on m.unit_code_a=u.unit_code and m.building_code i
s
> null
> left outer join buildings b1 on u.building_code=b1.building_code
> left outer join locations l1 on b1.location_code=l1.location_code
> left outer join buildings b2 on m.building_code=b2.building_code and
> m.unit_code_a is null
> left outer join locations l2 on b2.location_code=l2.location_code
>
> dean
> "Doug" <dbb211-hd204@.yahoo.com> wrote in message
> news:08311DB6-A81A-4F73-924D-9A8F8143B125@.microsoft.com...
>
>|||btw, I am using SQL Server 2000.
Doug|||FIrst, I am not trying to be sarcastic, just giving some friendly advice to
you and other posters that post questions without the necessary code to
allow us to help you quickly.
The diagram is nice but, If we are to help you write a query and test it to
make sure it does what you want, we need to have the tables created on our
database with the right structure and have sameple data in them.
This can happen in 2 ways:
1. We read your diagram and create the tables, relationships, etc from them
and then enter some sample data
2. You can provide us with the SQL script to accomplish this and save us a
lot of time
Which do you think will get you more help quicker? :-)
"Doug" <dbb211-hd204@.yahoo.com> wrote in message
news:96AB7DF5-EE89-41B8-8E93-224EDE8C0564@.microsoft.com...
> Dean and others. Please see
> [url]http://www.cedar.cr.cc/images/relationship.jpg[/url]
> for a relationship diagram of the tables in question. A brief description
> of
> why the relationships are as they are.
> As you can probably tell, this is an inventory (of computers). A building
> may or may not have units designated within it. If there are units in the
> building, the unit field will be populated, otherwise the building field
> will
> be populated (in tblCIMComputers). The second Unit field is to allow
> (usually) a person in another location to log into they system as though
> their computer was located in a specific Unit (our login security system
> also
> uses this table). As such, there may or may not be a value in this second
> Unit field.
> The reason for this type of layout is because Units can move from one
> building to another. If such a move is made, one record in one table is
> changed (i.e. BuildingCode in tblUnits) and all is well.
> The constructs of the tables are very straight forward. Only field
> definitions, primary and foreign keys. No other type of constraints. The
> purpose of the query I am trying to build is to bring back all pertinent
> data
> to provide the person accessing it with a complete overview of all data.
> "Dean" wrote:
>

complex(?) query

Hello experts.

I'm a novice sql writer and need some help in writing a query to
extract applicable data from the following table (titled EMPLOYEE):

--
ID_NUMBERCODEDATE
------ --- ---
12 VO20060914
12 XD20060913
12 AD20060912
12 WR20060911
12 AT20060910
45 VO20060914
45 XR20060913
45 AT20060912
45 AD20060911
45 AT20060910
78 AD20060914
78 AT20060913
78 VO20060912
78 AD20060911
78 AT20060910

I need to select ID_NUMBER
from EMPLOYEE
where CODE = 'VO'

caveat: I only want the ID_NUMBER(s) where the CODE = 'VO'
and the previous CODE (by DATE) = 'AD'
or the previous CODE (by DATE) = 'AD' with any CODE in between
except 'AT';

E.g., in the above example, the appropriate code should select
ID_NUMBER(s) 12 and 78 because
1. a VO code exists
2. an AD code (by DATE) precedes it
3. although 'AD' does not come immediately before 'VO' (in the
case of ID_NUMBER 12) 'AT' cannot be found in between

I hope I haven't confused anyone. Any help would be appreciated.Alex,

You seem to be almost there and you just have to put it all together to
come up with the answer.
To help you along, let's talk syntax and "NOT EXISTS"

1. Are you familiar with the syntax of a join that allows you to
select a subset of data before using it in the join.
As this applies to your case:

SELECT col1, col2, col3
FROM ( SELECT col1, col2, col3
FROM codes
WHERE code = '?' ) <tbl_alias>
INNER JOIN (SELECT col1, col2, col3
FROM codes
WHERE code = '?' ) <tbl_alias2>
ON tbl_alias1.col? = tbl_alias2.col?
< Add more join conditions >

2. NOT EXISTS is useful in your example. What do you want to NOT
EXIST?

Quote:

Originally Posted by

3. although 'AD' does not come immediately before 'VO'


(in the

Quote:

Originally Posted by

case of ID_NUMBER 12) 'AT' cannot be found in between


AND NOT EXISTS ( SELECT 1 FROM codes WHERE ? )
Remember in the N/E sub_select you will be comparing values in a
correlated sub_query.

I'll check back and post the answer if you are still having difficulty
but only after you post some sql that you have been trying to make
work.

alex wrote:

Quote:

Originally Posted by

Hello experts.
>
I'm a novice sql writer and need some help in writing a query to
extract applicable data from the following table (titled EMPLOYEE):
>
--
ID_NUMBERCODEDATE
------ --- ---
12 VO20060914
12 XD20060913
12 AD20060912
12 WR20060911
12 AT20060910
45 VO20060914
45 XR20060913
45 AT20060912
45 AD20060911
45 AT20060910
78 AD20060914
78 AT20060913
78 VO20060912
78 AD20060911
78 AT20060910
>
I need to select ID_NUMBER
from EMPLOYEE
where CODE = 'VO'
>
caveat: I only want the ID_NUMBER(s) where the CODE = 'VO'
and the previous CODE (by DATE) = 'AD'
or the previous CODE (by DATE) = 'AD' with any CODE in between
except 'AT';
>
E.g., in the above example, the appropriate code should select
ID_NUMBER(s) 12 and 78 because
1. a VO code exists
2. an AD code (by DATE) precedes it
3. although 'AD' does not come immediately before 'VO' (in the
case of ID_NUMBER 12) 'AT' cannot be found in between
>
I hope I haven't confused anyone. Any help would be appreciated.

|||Alex,

Let me update my previous post.
The subselects within the join are not necessary.
It is the NOT EXISTS that you should be interested in.
You will still have to join the table with itself to filter out the
rows for VO and AD within two separate aliased tables.

alex wrote:

Quote:

Originally Posted by

Hello experts.
>
I'm a novice sql writer and need some help in writing a query to
extract applicable data from the following table (titled EMPLOYEE):
>
--
ID_NUMBERCODEDATE
------ --- ---
12 VO20060914
12 XD20060913
12 AD20060912
12 WR20060911
12 AT20060910
45 VO20060914
45 XR20060913
45 AT20060912
45 AD20060911
45 AT20060910
78 AD20060914
78 AT20060913
78 VO20060912
78 AD20060911
78 AT20060910
>
I need to select ID_NUMBER
from EMPLOYEE
where CODE = 'VO'
>
caveat: I only want the ID_NUMBER(s) where the CODE = 'VO'
and the previous CODE (by DATE) = 'AD'
or the previous CODE (by DATE) = 'AD' with any CODE in between
except 'AT';
>
E.g., in the above example, the appropriate code should select
ID_NUMBER(s) 12 and 78 because
1. a VO code exists
2. an AD code (by DATE) precedes it
3. although 'AD' does not come immediately before 'VO' (in the
case of ID_NUMBER 12) 'AT' cannot be found in between
>
I hope I haven't confused anyone. Any help would be appreciated.

|||>>I'm a novice sql writer and need some help in writing a query to extract applicable data from the following table (titled EMPLOYEE): <<

First, let's clean up your missing DDL. The table name should tell us
what set of entities is modeled in the table; do you really have one
employee? Small firm! Try Personnel -- the collective name of the set
or something that tells us what the set is. Code is too vague --
postal code? Date is both too vague *and* a reserved word. A name
like "id_number" is also uselessly general; emp_id would be a better
choice. Since you did not post DDL, we have to guess at constaints and
keys. A skeleton of what you need is something like this:

CREATE TABLE PersonnelActions
(emp_id INTEGER NOT NULL,
action_date action_dateTIME DEFAULT CURRENT_TIMESTAMP NOT NULL,
PRIMARY KEY (emp_id, foobar_date),
action_code CHAR(2) NOT NULL
CHECK (foobar_code IN ('VO', 'XD'))
);

You need to read a book on data modeling and ISO-11179 rules for names.
I would also look up the use of UPPERCASE for names -- it is the worst
way to code, being about 8-12% harder to detect misspellings. That is
why books and newspapers use lowercase.

Quote:

Originally Posted by

Quote:

Originally Posted by

>I only want the emp_id(s) where the action_code = 'VO'


and the previous action_code (by action_date) = 'AD'
or the previous action_code (by action_date) = 'AD' with any
action_code in between
except 'AT'; <<

SELECT DISTINCT emp_id
FROM PersonnelAction AS PVO,
PersonnelAction AS PAD
WHERE PVO.emp_id = PAD.emp_id
AND PVO.action_code = 'VO'
AND PAD.action_code = 'AD'
AND PAD.action_date < PVO.action_date
AND NOT EXISTS
(SELECT *
FROM PersonnelAction AS PAT
WHERE PAT.action_code = 'AT'
AND PAT.emp_id = PVO.emp_id
AND PAT_action_date BETWEEN PAD.action_date AND
PVO.action_date);|||>>I'm a novice sql writer and need some help in writing a query to extract applicable data from the following table (titled EMPLOYEE): <<

First, let's clean up your missing DDL. The table name should tell us
what set of entities is modeled in the table; do you really have one
employee? Small firm! Try Personnel -- the collective name of the set
or something that tells us what the set is. Code is too vague --
postal code? Date is both too vague *and* a reserved word. A name
like "id_number" is also uselessly general; emp_id would be a better
choice. Since you did not post DDL, we have to guess at constaints and
keys. A skeleton of what you need is something like this:

CREATE TABLE PersonnelActions
(emp_id INTEGER NOT NULL,
action_date action_dateTIME DEFAULT CURRENT_TIMESTAMP NOT NULL,
PRIMARY KEY (emp_id, foobar_date),
action_code CHAR(2) NOT NULL
CHECK (foobar_code IN ('VO', 'XD'))
);

You need to read a book on data modeling and ISO-11179 rules for names.
I would also look up the use of UPPERCASE for names -- it is the worst
way to code, being about 8-12% harder to detect misspellings. That is
why books and newspapers use lowercase.

Quote:

Originally Posted by

Quote:

Originally Posted by

>I only want the emp_id(s) where the action_code = 'VO'


and the previous action_code (by action_date) = 'AD'
or the previous action_code (by action_date) = 'AD' with any
action_code in between
except 'AT'; <<

SELECT DISTINCT emp_id
FROM PersonnelAction AS PVO,
PersonnelAction AS PAD
WHERE PVO.emp_id = PAD.emp_id
AND PVO.action_code = 'VO'
AND PAD.action_code = 'AD'
AND PAD.action_date < PVO.action_date
AND NOT EXISTS
(SELECT *
FROM PersonnelAction AS PAT
WHERE PAT.action_code = 'AT'
AND PAT.emp_id = PVO.emp_id
AND PAT_action_date BETWEEN PAD.action_date AND
PVO.action_date);|||Alex,

It looks like CELKO gave you the answer along with a lot more
"advanced" advice. I hope you appreciate that I was trying to give you
a nudge to let you figure it out.

If you are still having trouble, post your SQL and we can make any
corrections.

Bill

alex wrote:

Quote:

Originally Posted by

Hello experts.
>
I'm a novice sql writer and need some help in writing a query to
extract applicable data from the following table (titled EMPLOYEE):
>
--
ID_NUMBERCODEDATE
------ --- ---
12 VO20060914
12 XD20060913
12 AD20060912
12 WR20060911
12 AT20060910
45 VO20060914
45 XR20060913
45 AT20060912
45 AD20060911
45 AT20060910
78 AD20060914
78 AT20060913
78 VO20060912
78 AD20060911
78 AT20060910
>
I need to select ID_NUMBER
from EMPLOYEE
where CODE = 'VO'
>
caveat: I only want the ID_NUMBER(s) where the CODE = 'VO'
and the previous CODE (by DATE) = 'AD'
or the previous CODE (by DATE) = 'AD' with any CODE in between
except 'AT';
>
E.g., in the above example, the appropriate code should select
ID_NUMBER(s) 12 and 78 because
1. a VO code exists
2. an AD code (by DATE) precedes it
3. although 'AD' does not come immediately before 'VO' (in the
case of ID_NUMBER 12) 'AT' cannot be found in between
>
I hope I haven't confused anyone. Any help would be appreciated.

|||--CELKO-- wrote:

Quote:

Originally Posted by

First, let's clean up your missing DDL. The table name should tell us
what set of entities is modeled in the table; do you really have one
employee? Small firm! Try Personnel -- the collective name of the set
or something that tells us what the set is.


What about "Employees"? But this is mostly grammatical pedantry; any
reasonable person will understand the implicit plural.

Quote:

Originally Posted by

Since you did not post DDL, we have to guess at constaints and
keys. A skeleton of what you need is something like this:
>
CREATE TABLE PersonnelActions
(emp_id INTEGER NOT NULL,
action_date action_dateTIME DEFAULT CURRENT_TIMESTAMP NOT NULL,
PRIMARY KEY (emp_id, foobar_date),
action_code CHAR(2) NOT NULL
CHECK (foobar_code IN ('VO', 'XD'))
);


"something like", indeed. That penultimate line should be more like
CHECK (action_code IN ('VO', 'XD', 'AD', 'WR', 'AT', 'XR'))
or should refer to an ActionCodes table, or should simply be omitted.

Quote:

Originally Posted by

SELECT DISTINCT emp_id


Need to specify whether it comes from PVO or PAD.

Quote:

Originally Posted by

FROM PersonnelAction AS PVO,
PersonnelAction AS PAD
WHERE PVO.emp_id = PAD.emp_id
AND PVO.action_code = 'VO'
AND PAD.action_code = 'AD'
AND PAD.action_date < PVO.action_date


The following is clearer IMO:

FROM PersonnelAction AS PEarlier
JOIN PersonnelAction AS PLater ON PEarlier.emp_id = PLater.emp_id
AND PEarlier.action_date < PLater.action_date
WHERE PEarlier.action_code = 'AD'
AND PLater.action_code = 'VO'

Quote:

Originally Posted by

AND NOT EXISTS
(SELECT *
FROM PersonnelAction AS PAT
WHERE PAT.action_code = 'AT'
AND PAT.emp_id = PVO.emp_id
AND PAT_action_date BETWEEN PAD.action_date AND
PVO.action_date);

Complex XML Parsing/Shredding

Hi,

I have generated a sample XML document from the XSD file using XMLSpy and used these in XML Source stage.

While I was parsing/Shredding the XML file and to write to sequential files I got the following error message.

The XML Source Adapter does not support mixed content model on Complex Types.

Additional Information:
Pipeline component has returned HRESULT error code )xC02092A1 from a method call. [Microsoft.SqlServer.DTSPipelineWrap]

Can anybody give a sample code with Complex XML type.

--

Find attached the XSD format. This is FYI.

Not sure I understand the question.

Empty, simple and element-only content models for complex types are supported, but mixed content is not.

Are you asking for a sample of a schema that has one of those content models?

|||

Are you able to get my XSD schema attached in my previous question? If not, could you please tell me how to send you the XSD schema

My schema content will be changed based on the instrument type.

For example,

<instrument type='Equity'>
<equityrelatedcolumns>value</equityrelatecolumns>
<pricinglist>
<price1/>
<price2/>
...
...
...
<pricen/>
</pricinglist>
</instrument>
<instrument type='Bond'>
<bondrelatedcolumns>value</bondrelatedcolumns>
<pricinglist>
<price1/>
<price2/>
...
...
...
<pricen/>
</pricinglist>
</instrument>

|||

Current SSIS support for loading XML does not support Complex Types with mixed content models. I looked at the schema provided and noticed several complex types with mixed="true" defined.

However, based on the XML sample provided, it is unclear to me why this is required since known of the element instances contained any non-element content. This would lead me to believe that at least fot the sample provided, you could change the content model on the ComplexTypes to not be mixed to work around the limitation of SSIS.

If this is not feasible, then you will have to preprocess te instance documents with an XSLT to turn the non-element content for the ComplexTypes with mixed content into element conent.

Hope that helps -

Andy

|||

Thanks Andy. The XSD file is the correct one. Our original XML file will contain mixed content type only.

We generated sample XML file through XMLSPY and specified NULL for all the contents. That is the reason the XML file looks like simple content.

Hope SSIS next version might look into this issue.

Complex where clause?

Hi,

I have a stored procedure with a few parameters. One of them is @.ProviderParam and it defaults to Null. If a value is passed into that parameter when the sp is called, I need to include a check for the provider in the where clause, like this:

Where <some other stuff> AND Provider = @.ProviderParam

But if nothing is passed into that parameter (and it defaults to Null), I need to do nothing with provider in the where clause. The where clause would look like this:

Where <some other stuff>

I believe the solution is to use a CASE statement in the where clause somehow, but I'm not sure how to proceed. Can anyone please help?

Thanks.

One way is to do something like:

AND ( @.ProviderParam is null or
Provider = @.ProviderParam)

If your PROVIDER column is a non-null column you also might be able to use:

AND Provider = ISNULL (@.ProviderParam, Provider)

Again, the column must be a NOT NULL column or this filter will not work correctly whenever both @.ProviderParam and Provider are null.

|||

If I understand your issue correctly, you wish to optionally provide a value for the @.ProviderParam, use it in the WHERE clause if it is available, otherwise if it is NULL, ignore @.ProviderParam. If so, this may work for you:

AND Provider = coalesce( @.ProviderParam, Provider )

As Kent indicated, Provider MUST be a NOT NULL column for this approach to work properly.

|||The advantage of coalesce is that it will also work with DB2 whereas ISNULL will not.|||

Great stuff. Thank you, both.

Provider is a null column. DB2 is not a factor. Kent's 1st solution is really elegant. It doesn't involve a function call, which is efficient, and it's so simple. Just too much elegance for me to pass by! :)

Thanks, again, for these insights.

|||

Just a note to say that the other advantage of COALESCE is that it can take an arbitrary number of arguments and returns the first one that is not null.

SET A_Value = COALESCE(First_Choice, Second_Choice, Desperate_Choice, Default_Value)

This can be useful if you have something like 3 different names you could use before giving up and using 'UNKNOWN'.

Complex View creation question

I need to create a cross-database view (same server) in a master database.
The databases I'm joining in the view are listed in a table in that master.
I'd like for the view to automatically include new databases whose names are
added to that table in the master. How would I go about doing this? I'm no
t
familiar with dynamic sql... TIA.Views aren't going to have dynamic SQL in them, and I wouldn't really
recommend a multi-line table user-defined function even though you could
probably accomplish what you want by using dynamic SQL in it.
I would recommend a hook in your application/middle-tier (optimally) or a
trigger on that master table (less optimal) that would ALTER the view to
include all the existing databases in your master table whenever the list of
databases changes. Just create the ALTER VIEW statement based on the list
from the master table. If done from the app, you have many ways to do this;
if from a trigger, you'd create the SQL string via a cursor or a funky
SELECT statement and then execute it via EXEC (dynamic SQL).
The things to consider in this scenario would be: what impact does changing
the view have on the live system? how frequently does this change? does
the user adding/deleting records in the master table have permissions to
alter the view?
Mike
"William Sullivan" <WilliamSullivan@.discussions.microsoft.com> wrote in
message news:AD0E4C8D-1983-4003-B8FE-09D0222548F4@.microsoft.com...
>I need to create a cross-database view (same server) in a master database.
> The databases I'm joining in the view are listed in a table in that
> master.
> I'd like for the view to automatically include new databases whose names
> are
> added to that table in the master. How would I go about doing this? I'm
> not
> familiar with dynamic sql... TIA.

Complex variable length string combination problem

Hi,
I'm having trouble finding a solution for the following problem:
Suppose you have the following string as input 'sig, ltw, onss'
I would like to generate the following result set:
sig
ltw
onss
sig, ltw
sig, onss
ltw, onns
sig, ltw, onss
This should also work for any number of names (each time seperated by a
comma) within the string ex.:
input = 'sig, ltw, onss, plk'
output =
sig
ltw
onss
plk
sig, ltw
sig, onss
sig, plk
ltw, onns
ltw, plk
onss, plk
sig, ltw, onss
sig, onss, plk
ltw, onss, plk
sig, ltw, onss, plk
Anyone an idea how to resolve this problem?
Thanx in advance...Why don't you put this data in a table rather than a delimited string? TSQL
really isn't a language for string manipulation and delimited data just
shouldn't exist in the database.
The permutations you want to output could be achieved with a self- CROSS
JOIN once you've put the data in a table.
David Portas
SQL Server MVP
--|||You can also do it with the ROLLUP operator:
CREATE TABLE foo (x VARCHAR(5) PRIMARY KEY)
INSERT INTO foo VALUES ('sig')
INSERT INTO foo VALUES ('ltw')
INSERT INTO foo VALUES ('onss')
SELECT A.x, B.x, C.x
FROM foo AS A
JOIN foo AS B
ON B.x <> A.x
JOIN foo AS C
ON C.x <> A.x
AND C.x <> B.x
GROUP BY A.x, B.x, C.x WITH ROLLUP
David Portas
SQL Server MVP
--|||Hi,
I agree that string manipulation is not so easy in T-SQL.
Suppose I put the words as rows in a table; the problem with the crossjoin
is that it returns too many possiblities that are not usefull to me:
given a, b, c
the crossjoin would generate:
a, a, a
a, b, a
a, c, a
b, a, a => already exists but in another order
etc...
As you see whereas in my case I generate 14 possibilities for a 4 names
comma seperated string in your case this will be 27 possibilities; in other
words almost twice as many.
A solution would be to elimate from the crossjoin result the same occurences
of the names but in another order. But how?
"David Portas" wrote:

> Why don't you put this data in a table rather than a delimited string? TSQ
L
> really isn't a language for string manipulation and delimited data just
> shouldn't exist in the database.
> The permutations you want to output could be achieved with a self- CROSS
> JOIN once you've put the data in a table.
> --
> David Portas
> SQL Server MVP
> --|||This is pretty close; if we could just eliminate the "doubles" (in this case
the same names but in a different order) than I would be a happy man... ;-)
"David Portas" wrote:

> You can also do it with the ROLLUP operator:
> CREATE TABLE foo (x VARCHAR(5) PRIMARY KEY)
> INSERT INTO foo VALUES ('sig')
> INSERT INTO foo VALUES ('ltw')
> INSERT INTO foo VALUES ('onss')
> SELECT A.x, B.x, C.x
> FROM foo AS A
> JOIN foo AS B
> ON B.x <> A.x
> JOIN foo AS C
> ON C.x <> A.x
> AND C.x <> B.x
> GROUP BY A.x, B.x, C.x WITH ROLLUP
> --
> David Portas
> SQL Server MVP
> --
>|||Try this one then:
CREATE TABLE foo (x VARCHAR(5) PRIMARY KEY)
INSERT INTO foo VALUES ('sig')
INSERT INTO foo VALUES ('ltw')
INSERT INTO foo VALUES ('onss')
INSERT INTO foo VALUES ('')
SELECT A.x, NULLIF(B.x,''), NULLIF(C.x,'')
FROM foo AS A
LEFT JOIN foo AS B
ON B.x < A.x
LEFT JOIN foo AS C
ON C.x < B.x
WHERE A.x > ''
David Portas
SQL Server MVP
--|||David,
Great!!!! this is exactly what I need.
Is there an easy way to make this code dynamic as to receive any number of
input rows?
This already is great to work on...
thanx man! :-)
"David Portas" wrote:

> Try this one then:
> CREATE TABLE foo (x VARCHAR(5) PRIMARY KEY)
> INSERT INTO foo VALUES ('sig')
> INSERT INTO foo VALUES ('ltw')
> INSERT INTO foo VALUES ('onss')
> INSERT INTO foo VALUES ('')
> SELECT A.x, NULLIF(B.x,''), NULLIF(C.x,'')
> FROM foo AS A
> LEFT JOIN foo AS B
> ON B.x < A.x
> LEFT JOIN foo AS C
> ON C.x < B.x
> WHERE A.x > ''
> --
> David Portas
> SQL Server MVP
> --
>|||The following is really slow, (cause it's resursive), but it works...
First step would be to get the Indiv Strings into a table.. You can use the
following function for that... It's a generally useful function to have
around anyway...
Create Function dbo.ParseString (
@.S VarChar(8000),
@.delim Char(1))
Returns @.tOut Table (ValNum Integer Primary Key Identity, sVal VarChar(500)
)
As
Begin
Declare @.sVal VarChar(80)
Declare @.deLimPos Integer
If right(@.S,1) <> @.Delim Set @.S = @.S + @.Delim
While Len(@.S) > 0
Begin
Set @.deLimPos = CharIndex(@.delim, @.S)
Set @.sVal = Left(@.S,@.deLimPos -1)
Set @.S = Right(@.S,Len(@.S) - @.deLimPos)
Insert @.tOut (sVal) Values (@.sVal)
End
Return
End
-- ----
This function parses a string, using the supplied delimiter, and returns a
table with one row for each entry in the string.
Next, you need a function to "alphabeticize" a delimited string... This one
does the trick...
Create FUNCTION dbo.SortString
(@.S VarChar(1000), @.Delim Char(1))
RETURNS VarChar(1000)
AS
BEGIN
Declare @.Out VarChar(1000) Set @.Out = ''
Declare @.Vals Table (Val VarChar(100))
Declare @.Val VarChar(100)
Insert @.Vals(Val)
Select LTrim(sVal)
From dbo.ParseString(@.S, @.Delim)
While Exists(Select * From @.Vals) Begin
Select @.Val = Min(Val) From @.Vals
Set @.Out = @.Out + @.Val + ','
Delete @.Vals Where Val = @.Val
End
Return Substring(@.Out, 1, Len(@.Out) -1)
END
-- ----
Using these 2 functions, you can dynamically do what you want wit hteh
following:
assuming the variable @.Input contains the original concatenated string...
Declare @.Input VarChar(100) Set @.Input = 'a, b, c'
Declare @.Items Table (ItmNo Integer Primary Key Identity, item varchar(50))
Declare @.Permutations Table(Permutation VarChar(1000))
Insert @.Items (Item)
Select sVal
From dbo.ParseString(@.Input , ',')
Order By sVal
-- ---
--Select * From @.Items
Declare @.NumItems TinyInt
Declare @.Size TinyInt Set @.Size = 0
Select @.NumItems = Count(*) From @.Items
While @.Size <= @.NumItems Begin
Insert @.Permutations (Permutation)
Select Distinct dbo.SortString(IsNull(P.Permutation + ', ', '') +
I.Item, ',')
From @.Items I Left Join @.Permutations P
On I.Item <> IsNull(P.Permutation,'')
Where Not Exists(Select * From @.Permutations
Where Permutation =
dbo.SortString(IsNull(P.Permutation + ', ', '') +
I.Item, ','))
And CharIndex(I.Item, IsNull(P.Permutation,'')) = 0
Set @.Size = @.Size + 1
End
Insert @.Permutations(Permutation) Values('')
Select * From @.Permutations|||Thanks man for your effort.
Will stick to the answer of David Portas found it very elegant.
"CBretana" wrote:

> The following is really slow, (cause it's resursive), but it works...
> First step would be to get the Indiv Strings into a table.. You can use th
e
> following function for that... It's a generally useful function to have
> around anyway...
> Create Function dbo.ParseString (
> @.S VarChar(8000),
> @.delim Char(1))
> Returns @.tOut Table (ValNum Integer Primary Key Identity, sVal VarChar(50
0))
> As
> Begin
> Declare @.sVal VarChar(80)
> Declare @.deLimPos Integer
> If right(@.S,1) <> @.Delim Set @.S = @.S + @.Delim
> While Len(@.S) > 0
> Begin
> Set @.deLimPos = CharIndex(@.delim, @.S)
> Set @.sVal = Left(@.S,@.deLimPos -1)
> Set @.S = Right(@.S,Len(@.S) - @.deLimPos)
> Insert @.tOut (sVal) Values (@.sVal)
> End
> Return
> End
> -- ----
> This function parses a string, using the supplied delimiter, and returns a
> table with one row for each entry in the string.
> Next, you need a function to "alphabeticize" a delimited string... This on
e
> does the trick...
> Create FUNCTION dbo.SortString
> (@.S VarChar(1000), @.Delim Char(1))
> RETURNS VarChar(1000)
> AS
> BEGIN
> Declare @.Out VarChar(1000) Set @.Out = ''
> Declare @.Vals Table (Val VarChar(100))
> Declare @.Val VarChar(100)
> Insert @.Vals(Val)
> Select LTrim(sVal)
> From dbo.ParseString(@.S, @.Delim)
> While Exists(Select * From @.Vals) Begin
> Select @.Val = Min(Val) From @.Vals
> Set @.Out = @.Out + @.Val + ','
> Delete @.Vals Where Val = @.Val
> End
> Return Substring(@.Out, 1, Len(@.Out) -1)
> END
> -- ----
> Using these 2 functions, you can dynamically do what you want wit hteh
> following:
> assuming the variable @.Input contains the original concatenated string...
> Declare @.Input VarChar(100) Set @.Input = 'a, b, c'
> Declare @.Items Table (ItmNo Integer Primary Key Identity, item varchar(50)
)
> Declare @.Permutations Table(Permutation VarChar(1000))
> Insert @.Items (Item)
> Select sVal
> From dbo.ParseString(@.Input , ',')
> Order By sVal
> -- ---
> --Select * From @.Items
> Declare @.NumItems TinyInt
> Declare @.Size TinyInt Set @.Size = 0
> Select @.NumItems = Count(*) From @.Items
>
> While @.Size <= @.NumItems Begin
> Insert @.Permutations (Permutation)
> Select Distinct dbo.SortString(IsNull(P.Permutation + ', ', '') +
> I.Item, ',')
> From @.Items I Left Join @.Permutations P
> On I.Item <> IsNull(P.Permutation,'')
> Where Not Exists(Select * From @.Permutations
> Where Permutation =
> dbo.SortString(IsNull(P.Permutation + ', ', '')
+
> I.Item, ','))
> And CharIndex(I.Item, IsNull(P.Permutation,'')) = 0
> Set @.Size = @.Size + 1
> End
> Insert @.Permutations(Permutation) Values('')
> Select * From @.Permutations
>|||No problemo Peter,
David's solution is much more elegant, and much faster, but as you noticed,
it not dynamic as to the number of items in the imput string...
But as I'm sure you have already figured out, the required processing to
solve this problem increases very very fast as the number of items increases
.
Regards,
Charly
"PeterM" wrote:
> Thanks man for your effort.
> Will stick to the answer of David Portas found it very elegant.
> "CBretana" wrote:
>

Complex variable length combinations of a string

Hi,
Could anyone help me with the following complex problem:
Suppose I have the following input: 'sig, ltw, onss'
Than my output should give the following result set:
sig
ltw
onss
sig, ltw
sig, onss
ltw, onss
sig, ltw, onss
The solution should also work with any given number of names in my comma
seperated string ex.:
input = sig, ltw, onss, pkl
output =
sig
ltw
onss
pkl
sig, ltw
sig, onss
sig, pkl
ltw, onss
ltw, pkl
onss, pkl
sig, ltw, onss
sig, onss, pkl
ltw, onss, pkl
sig, ltw, onss, pkl
Anyone an idea how to resolve this with T-SQL?
Thanx...Peter,
Took me some time to figure this out:
set nocount on
declare @.str as varchar(8000)
,@.count as int
,@.out as varchar(8000)
create table #str
(i int identity(0, 1)
, el varchar(4000))
set @.str='sig, ltw, onss'
--extract elements into a table
set @.str = @.str + ','
while @.str <> '' begin
insert into #str (el)
values (substring(@.str, 1, charindex(',', @.str) - 1))
set @.str = ltrim(substring(@.str, charindex(',', @.str) + 1, 8000))
end
--calculate number of combinations
select @.count = power(2, count(*)) - 1 from #str
--create all combinations
--each element as a binary position where
--1 means element is in and 0 means element is not in a given combination
while @.count > 0 begin
set @.out = ''
select @.out = @.out + el + ', '
from #str
where @.count & power(2, i) = power(2, i)
order by i
select left(@.out, len(@.out) - 1)
set @.count = @.count - 1
end
drop table #str
Ilya
"PeterM" <PeterM@.discussions.microsoft.com> wrote in message
news:A2E5AF3D-4AEF-4E79-9395-639513E06D4E@.microsoft.com...
> Hi,
> Could anyone help me with the following complex problem:
> Suppose I have the following input: 'sig, ltw, onss'
> Than my output should give the following result set:
> sig
> ltw
> onss
> sig, ltw
> sig, onss
> ltw, onss
> sig, ltw, onss
> The solution should also work with any given number of names in my comma
> seperated string ex.:
> input = sig, ltw, onss, pkl
> output =
> sig
> ltw
> onss
> pkl
> sig, ltw
> sig, onss
> sig, pkl
> ltw, onss
> ltw, pkl
> onss, pkl
> sig, ltw, onss
> sig, onss, pkl
> ltw, onss, pkl
> sig, ltw, onss, pkl
> Anyone an idea how to resolve this with T-SQL?
> Thanx...
>|||Ilya, Thanks for your effort in resolving this; but look at the post just
before (Oops I sended it twice) the answer of David Portas is such a elegant
solution, you have to see it to belief it :-)
Thanx
"Ilya Margolin" wrote:

> Peter,
> Took me some time to figure this out:
> set nocount on
> declare @.str as varchar(8000)
> ,@.count as int
> ,@.out as varchar(8000)
> create table #str
> (i int identity(0, 1)
> , el varchar(4000))
> set @.str='sig, ltw, onss'
> --extract elements into a table
> set @.str = @.str + ','
> while @.str <> '' begin
> insert into #str (el)
> values (substring(@.str, 1, charindex(',', @.str) - 1))
> set @.str = ltrim(substring(@.str, charindex(',', @.str) + 1, 8000))
> end
> --calculate number of combinations
> select @.count = power(2, count(*)) - 1 from #str
> --create all combinations
> --each element as a binary position where
> --1 means element is in and 0 means element is not in a given combination
> while @.count > 0 begin
> set @.out = ''
> select @.out = @.out + el + ', '
> from #str
> where @.count & power(2, i) = power(2, i)
> order by i
> select left(@.out, len(@.out) - 1)
> set @.count = @.count - 1
> end
> drop table #str
> Ilya
>
> "PeterM" <PeterM@.discussions.microsoft.com> wrote in message
> news:A2E5AF3D-4AEF-4E79-9395-639513E06D4E@.microsoft.com...
>
>|||Peter,
That was my first thought. The downside of it you have to modify the
statement to add more joins as you add combination members, so the solution
is not scalable.
Ilya
"PeterM" <PeterM@.discussions.microsoft.com> wrote in message
news:D5230490-26F4-4E72-915B-53688DFFC618@.microsoft.com...
> Ilya, Thanks for your effort in resolving this; but look at the post just
> before (Oops I sended it twice) the answer of David Portas is such a
elegant
> solution, you have to see it to belief it :-)
> Thanx
> "Ilya Margolin" wrote:
>
combination
comma|||You're right !
I was wondering how big the difference in performance is between the two
solutions? Have to try it out...
Thanx again :-)
"Ilya Margolin" wrote:

> Peter,
> That was my first thought. The downside of it you have to modify the
> statement to add more joins as you add combination members, so the solutio
n
> is not scalable.
> Ilya
> "PeterM" <PeterM@.discussions.microsoft.com> wrote in message
> news:D5230490-26F4-4E72-915B-53688DFFC618@.microsoft.com...
> elegant
> combination
> comma
>
>|||Ilya,
I had to write you back to say that your solution is by far the most elegant
of all.
I had to take some time to understand your solution but once I understood
it; I found it just brilliant.
Sorry for this late appreciation of your solution ;-)
Thanx again,
Peter
"Ilya Margolin" wrote:

> Peter,
> That was my first thought. The downside of it you have to modify the
> statement to add more joins as you add combination members, so the solutio
n
> is not scalable.
> Ilya
> "PeterM" <PeterM@.discussions.microsoft.com> wrote in message
> news:D5230490-26F4-4E72-915B-53688DFFC618@.microsoft.com...
> elegant
> combination
> comma
>
>

Complex use of apostrophes

Hello,

could someone help with this query in a stored proc.?

SET @.SQL='SET '''+ @.avgwgt+''' = '

'(SELECT AVG(AverageWeight)

FROM CageFishHistory where CageID IN ('

+ @.cagearray+')

and ItemDate ='''

+CONVERT(varchar(23),@.startdate)+''')'

EXEC @.SQL

I'm trying to get an average value across dynamically selected rows. (I'm using a list array to deliver the selection to the stored proc). I need to re-use the average value within the procedure,so it's not enough to output it as a column of the resultset - EG. 'Select AVG(AverageWeight) as AvgWgt' . If I take out the @.avgwgt line it works fine, but otherwise I'm getting this error:

"Incorrect syntax near '(SELECT AVG(AverageWeight)

FROM CageFishHistory where CageID IN ('."

It may be that I can access a column of the resultset in the rest of the procedure, and that would help avoid the use of pesky apostrophes, but I don't know how to do it.

please, try like this.

SELECT @.avgwgt=AVG(AverageWeight) FROM CageFishHistory where CageID IN ('+ @.cagearray+') and ItemDate ='''+CONVERT(varchar(23),@.startdate)+''')'

Regards,

Omer Kamal

www.friendspoint.de

|||

I tried this Omer,and got

Conversion failed when converting the varchar value ' + @.cagearray + ' to data type int.

|||

Seems to be working now with the Split() Function I found - I'm posting in case it will help others...

SELECT

@.avgwgt=AVG(AverageWeight)FROM CageFishHistorywhere CageIDIN(SELECT ItemFROM dbo.Split(@.cagearray,','))and ItemDate=''+CONVERT(varchar(23),@.startdate)

====================================================================

set

ANSI_NULLSON

set

QUOTED_IDENTIFIERON

go

CREATE

FUNCTION [dbo].[Split]

(

@.ItemList

NVARCHAR(4000),

@.delimiter

CHAR(1)

)

RETURNS

@.IDTableTABLE(ItemVARCHAR(50))

AS

BEGIN

DECLARE @.tempItemListNVARCHAR(4000)SET @.tempItemList= @.ItemListDECLARE @.iINTDECLARE @.ItemNVARCHAR(4000)SET @.tempItemList=REPLACE(@.tempItemList,' ','')SET @.i=CHARINDEX(@.delimiter, @.tempItemList)WHILE(LEN(@.tempItemList)> 0)BEGINIF @.i= 0SET @.Item= @.tempItemListELSESET @.Item=LEFT(@.tempItemList, @.i- 1)INSERTINTO @.IDTable(Item)VALUES(@.Item)IF @.i= 0SET @.tempItemList=''ELSESET @.tempItemList=RIGHT(@.tempItemList,LEN(@.tempItemList)- @.i)SET @.i=CHARINDEX(@.delimiter, @.tempItemList)ENDRETURN

END

Complex UPDATE

Given the 2 tables Sponsor and SponsorEvent with SponsorID on SponsorEvent
as a FK
CREATE TABLE [dbo].[Sponsor] (
[SponsorID] [int] NOT NULL ,
[SponsorCode] [char] (15) NOT NULL ,
[BrandID] [int] NOT NULL ,
[FirstDate] [int] NOT NULL
) ON [PRIMARY]
GO
ALTER TABLE [dbo].[Sponsor] WITH NOCHECK ADD
CONSTRAINT [PK_Sponsor] PRIMARY KEY CLUSTERED
(
[SponsorID]
) WITH FILLFACTOR = 90 ON [PRIMARY]
GO
CREATE TABLE [dbo].[SponsorEvent] (
[Date] [int] NOT NULL ,
[BarbChanID] [int] NOT NULL ,
[StartTime] [int] NOT NULL ,
[AreaFlags] [smallint] NOT NULL ,
[PlatformFlags] [tinyint] NOT NULL ,
[EndTime] [int] NOT NULL ,
[SponsorID] [int] NOT NULL ,
[SponsorICodeID] [int] NOT NULL ,
[SponsorINameID] [int] NOT NULL
) ON [PRIMARY]
ALTER TABLE [dbo].[SponsorEvent] WITH NOCHECK ADD
CONSTRAINT [PK_SponsorEvent] PRIMARY KEY CLUSTERED
(
[Date],
[BarbChanID],
[StartTime],
[AreaFlags],
[PlatformFlags]
) WITH FILLFACTOR = 90 ON [PRIMARY]
what is wrong with this syntax
update Sponsor set FirstDate = att.[Date]
from (
SELECT SponsorID,MIN([DATE]) From SponsorEvent GROUP by SponsorID)
att,Sponsor s
where s.SponsorID = att.SponsorID
Query Analyser complains of
"No column was specified for column 2 of 'att'."
I am trying to group by SponsorID on SponsorEvent, work out what the minimum
date is on SponsorEvent and update [Date] on Sponsor with this where
SponsorID is in common.
Thanks
Stephen Howe> Query Analyser complains of
> "No column was specified for column 2 of 'att'."
Isn't it "No column NAME was specified...?"
This happens when you apply a calculation on a column and don't include an
alias. The outer query doesn't see a column named "Date", it only sees the
expression MIN([Date]), which is not the same thing.
How about :
UPDATE Sponsor
SET FirstDate = att.FirstDate
FROM Sponsor
INNER JOIN
(
SELECT SponsorID, [Date] = MIN([DATE])
FROM SponsorEvent
GROUP by SponsorID
) Att
ON s.SponsorID = att.SponsorID
Or, better yet, instead of having to run this update every single time the
SponsorEvent changes, drop the column firstdate from the sponsor table.
There is no reason to store this redundant information when you can always
get it directly from SponsorEvent.
As an aside, I recommend renaming the column [Date]. It is never a good
idea to use reserved words as column names.
A|||Sorry, forgot the s:

> FROM Sponsor
Should be
FROM Sponsor s|||Thanks for response

> Isn't it "No column NAME was specified...?"
No. Definitely not. What I wrote was copy and pasted out of QA.
There is a message in colour red just before. The full message is
Server: Msg 8155, Level 16, State 2, Line 1
No column was specified for column 2 of 'att'.

> How about :
> UPDATE Sponsor
> SET FirstDate = att.FirstDate
> FROM Sponsor
> INNER JOIN
> (
> SELECT SponsorID, [Date] = MIN([DATE])
> FROM SponsorEvent
> GROUP by SponsorID
> ) Att
> ON s.SponsorID = att.SponsorID
Does not work. I changed text to
SET FirstDate = att.[Date]
FROM Sponsor s
and now I get
"Server: Msg 107, Level 16, State 2, Line 1
The column prefix 'att' does not match with a table name or alias name used
in the query."

> Or, better yet, instead of having to run this update every single time the
> SponsorEvent changes, drop the column firstdate from the sponsor table.
> There is no reason to store this redundant information when you can always
> get it directly from SponsorEvent.
Yes you are right and I would like to.
But the reason why is that we have a analogous situation for tables where
Sponsor and SponsorEvent which have SponsorID in common
is reproduced with
SpotFilm and Spot which have SpotFilmID in common
SpotFilm and Sponsor have identical columns apart from the ID fields. It is
also such that if you concatenated them, the ID's are unique, no row in
common.
I say "somewhat symmetrical" because the difference is that data in
SponsorEvent is split between Spot and Slot.
Spot as a table has over 100 million rows (and gets larger per w).
Working out MIN([Date]) for each SpotFilmID on Spot is a triple-join between
Spot,Slot and SpotFilm, and we need to export that every Thursday. FirstDate
just happens to be a compromise. I know what you are saying, and I agree in
principal. At some point this year the server will be upgraded from SQL
Server 7 to 2000 and maybe the optimisation might be better.

> As an aside, I recommend renaming the column [Date]. It is never a good
> idea to use reserved words as column names.
I know. Noted. We have a table called [Break] which I am loathe to change.
Granted it is a keyword, but in the industry I am in "Break" is the most
descriptive word there is for the data it contains. They really are called
"Commercial Breaks". But I will change [Date] :-)
Stephen Howe|||What, do you have a case sensitive collation? Try using att everywhere and
no Att vs. att?
This works fine for me. You might want to provide similar DDL in the future
to make it easier for others to reproduce your scenario and test their
results. (See http://www.aspfaq.com/5006)
USE Tempdb
GO
CREATE TABLE Sponsor
(
SponsorID INT,
FirstDate SMALLDATETIME
)
GO
CREATE TABLE SponsorEvent
(
SponsorID INT,
[Date] SMALLDATETIME
)
GO
SET NOCOUNT ON
INSERT Sponsor SELECT 1, NULL
INSERT Sponsor SELECT 2, NULL
INSERT Sponsor SELECT 3, NULL
INSERT Sponsor SELECT 4, NULL
INSERT SponsorEvent SELECT 1, '20010501'
INSERT SponsorEvent SELECT 1, '20010601'
INSERT SponsorEvent SELECT 1, '20040801'
INSERT SponsorEvent SELECT 3, '20040701'
INSERT SponsorEvent SELECT 3, '20010601'
INSERT SponsorEvent SELECT 4, '20030801'
GO
UPDATE Sponsor
SET FirstDate = att.FirstDate
FROM Sponsor s
INNER JOIN
(
SELECT SponsorID, FirstDate = MIN([Date])
FROM SponsorEvent
GROUP BY SponsorID
) att
ON s.SponsorID = att.SponsorID
GO
SELECT * FROM Sponsor
GO
DROP TABLE SponsorEvent, Sponsor
GO
On 3/12/05 12:57 PM, in article ORy87zyJFHA.2716@.TK2MSFTNGP15.phx.gbl,
"Stephen Howe" <stephenPOINThoweATtns-globalPOINTcom> wrote:

> Thanks for response
>
> No. Definitely not. What I wrote was copy and pasted out of QA.
> There is a message in colour red just before. The full message is
> Server: Msg 8155, Level 16, State 2, Line 1
> No column was specified for column 2 of 'att'.
>
> Does not work. I changed text to
> SET FirstDate = att.[Date]
> FROM Sponsor s
> and now I get
> "Server: Msg 107, Level 16, State 2, Line 1
> The column prefix 'att' does not match with a table name or alias name use
d
> in the query."
>
> Yes you are right and I would like to.
> But the reason why is that we have a analogous situation for tables where
> Sponsor and SponsorEvent which have SponsorID in common
> is reproduced with
> SpotFilm and Spot which have SpotFilmID in common
> SpotFilm and Sponsor have identical columns apart from the ID fields. It i
s
> also such that if you concatenated them, the ID's are unique, no row in
> common.
> I say "somewhat symmetrical" because the difference is that data in
> SponsorEvent is split between Spot and Slot.
> Spot as a table has over 100 million rows (and gets larger per w).
> Working out MIN([Date]) for each SpotFilmID on Spot is a triple-join between
> Spot,Slot and SpotFilm, and we need to export that every Thursday. FirstDa
te
> just happens to be a compromise. I know what you are saying, and I agree i
n
> principal. At some point this year the server will be upgraded from SQL
> Server 7 to 2000 and maybe the optimisation might be better.
>
> I know. Noted. We have a table called [Break] which I am loathe to change.
> Granted it is a keyword, but in the industry I am in "Break" is the most
> descriptive word there is for the data it contains. They really are called
> "Commercial Breaks". But I will change [Date] :-)
> Stephen Howe
>
>
>|||> Sorry, forgot the s:
>
> Should be
> FROM Sponsor s
Thanks Aaaron, done it
UPDATE Sponsor
SET FirstDate = att.[Date]
FROM
(SELECT SponsorID, [Date] = MIN([DATE])
FROM SponsorEvent
GROUP by SponsorID
) Att INNER JOIN Sponsor s ON Att.SponsorID=s.SPonsorID|||> What, do you have a case sensitive collation? Try using att everywhere
and
> no Att vs. att?
I don't think we do. Anything to do with SQL Server 7 not recognising the
syntax?
Perhaps SQL Server 2000 is "improved" in that order does not matter
I changed the order putting Sponsor s last, (after the SELECT .. GROUP BY)
and at that point it recognised it.
Strange
But thanks
Stephen|||Date is not just a reserved word, it is too vague to be a valid data
element name -- date of what' Is there only one sponsor, as you
showed with a singular name? If you were writing SQL instead of a
strange dialect, would this be what you meant? It is a bad practice to
name relationship tables by concatenating names together -- always ask
if the relationship has its own name. Endorsements, sponsorships, etc.
UPDATE Sponsors
SET firstdate -- of what'
= (SELECT MIN(foobar_date)
FROM Endorsements AS E
WHERE E.sponsor_id = Sponsors.sponsor_id)
You might want to read a book on SQL and see what the standard UPDATE
syntax is.
And get a book on data modeling. Names like "SponsorICodeID" make
absolutley no sense. A code is not an identifier; it is a scalar value
on a nominal scale. Most of the rest of your DDL looks like you are
writing SQL with flags, etc. -- all the classic mistakes of someone who
does not know how to make a schema.|||"--CELKO--" <jcelko212@.earthlink.net> wrote in message
news:1110772877.481289.236930@.l41g2000cwc.googlegroups.com...
> It is a bad practice to name relationship tables by concatenating
names together
Mr. Celko,
Really? I've been doing a lot of that lately (sometimes M-to-M
relationships are stumpers). Is that a part of a standard I can take
a look at? Perhaps you could provide a weblink to an article or other
work with an extensive description of why it is bad, and the process
of doing better.
Sincerely,
Chris O.|||>> [name relationship tables by concatenating names together ] I've
been doing a lot of that lately (sometimes M-to-M relationships are
stumpers). <<
Not if you start from a data model. Relationships important enough to
be modeled tend to have names -- "Marriages" instead "ManWoman' or even
worse "CivilUnions" instead of "ManMan_WomanWoman_ManWomen". A
relationship name invites the attributes that go with the relationship;
Marriages implies a wedding date, license number, etc.
Google up ISO-11179; the principle is to name a thing for what it *is*,
not for what it *does* in a particular situation, not for hopw you
build it-- i.e. this is an "automobile", not a "TiresFrameMotor"; the
whole not the parts.
an extensive description of why it is bad, and the process of doing
better. <<
Look for an entire book on SQL style about the middle of this year from
me.

Complex T-SQL

Guys
I have a data table that contains emails that could come from one or
more source. I want to add a column to the table to reflect the
combination of sources that the record came from.
Basically I am trying to create the hybird_src and the hybrid tables
from the data_table. Then I want to update a new column on data table
with hybrid_id.
I know I can do this with a cursor, but it seems like there should be a
better (set based) way to accomplish this. Does anyone have any
suggestions?
create table #data_table(email_id int,src_id int)
--raw data
insert into #data_table (1,5)
insert into #data_table (1,6)
insert into #data_table (1,7)
insert into #data_table (2,5)
insert into #data_table (2,6)
insert into #data_table (2,7)
insert into #data_table (3,5)
insert into #data_table (3,6)
insert into #data_table (3,7)
insert into #data_table (4,5)
insert into #data_table (4,6)
insert into #data_table (5,5)
insert into #data_table (5,9)
insert into #data_table (5,4)
insert into #data_table (5,20)
insert into #data_table (6,20)
insert into #data_table (6,5)
insert into #data_table (6,9)
insert into #data_table (6,4)
create table #hybrid_src (hybrid_id int,src_id int)
--results I am looking for
insert into #hybrid_src (1,5)
insert into #hybrid_src (1,6)
insert into #hybrid_src (1,7)
insert into #hybrid_src (2,5)
insert into #hybrid_src (2,6)
insert into #hybrid_src (3,5)
insert into #hybrid_src (3,9)
insert into #hybrid_src (3,4)
insert into #hybrid_src (3,20)
create table #hybrid(hybrid_id int,hybrid_name varchar(200))
--results I am looking for
INSERT INTO #hybrid(1,'5,6,7')
INSERT INTO #hybrid(2,'5,6')
INSERT INTO #hybrid(3,'4,5,9,20')Dave wrote:
> Guys
> I have a data table that contains emails that could come from one or
> more source. I want to add a column to the table to reflect the
> combination of sources that the record came from.
> Basically I am trying to create the hybird_src and the hybrid tables
> from the data_table. Then I want to update a new column on data table
> with hybrid_id.
> I know I can do this with a cursor, but it seems like there should be a
> better (set based) way to accomplish this. Does anyone have any
> suggestions?
>
Why would you want to destroy the apparently sensible and practical
design you already have by kludging it into the "hybrid" tables that
you say you want? Concatenating lots of values together in a column
just results in redundancy and denormalization. If you need to display
it that way in a report then do it in your presentation tier, not in
the database.
David Portas
SQL Server MVP
--|||I am trying to accurately reflect which source an email came from.
Since an email can belong to more than one source it makes since (at
least to me so far) to report on a hybrid of all the valid sources.
If I model email transactions in a Datamart the fact grain would be the
email. I need a source dimension.
Any feedback on this would be very helpful. Including a better way to
model this.

complex tables - want to join to get one row of results from multiple rows

Hi there

This is a hard problem that I have - I have only been using sql for a couple of weeks and have gone past my ability level quickly! The real tables are complex but I will post a simple and a real version with the hope someone can help me.

Any help would be much appreciated - I would also be happy to pay someone to actually do it if it takes time to work out as I know that its hard when all your help is free :)
================================================
SIMPLE VERSION
Table 1 Dog breeds
dogbreedID, dogBreedName, colour
1,labrador,golden
2,beagle, tricolour
3,great dane, marle

Table 2 - maps criteria to dog breeds
dogbreedID, criteriaID, value, location
3,2,easy to train, c:/filepath2
1,1,good with children, c:/filepath
1,2,easy to train, c:/filepath2
2,1,good with children, c:/filepath
3,3,stranger friendly, c:/filepath3

So that leads to table 3 sitting behind the scenes not used in this query:
criteriaID, value, location
1,good with children, c:/filepath
2,easy to train, c:/filepath2
3,stranger friendly, c:/filepath3

I want a view that has the following:
dogbreedID, dogBreedName, colour, criteriaID1, value1, location1, criteriaID2, value2, location2, criteriaID3, value3, location3,criteriaID4, value4, location4

1,labrador,golden,1,good with children, c:/filepath,2,easy to train, c:/filepath2,NULL,NULL,NULL,NULL, NULL, NULL

2,beagle, tricolour,1,good with children,NULL, NULL, NULL,NULL, NULL, NULL,NULL, NULL, NULL

3,great dane, marle,NULL, NULL, NULL,2,easy to train, c:/filepath2,3,stranger friendly, c:/filepath3

================================================== =====
more complicated view - you can see each table is actually a combination of table values but I dont think that matters to this problem - the above example is fine but I am not very good with this so may have left somehting out that you can derive from the example below:
Table 1:
SELECT distinct dbo.BREED_dogBreeds.breedId, dbo.BREED_dogBreeds.breedName, dbo.BREED_dogBreeds.alternativeName, dbo.BREED_dogBreeds.shortDesc,
dbo.BREED_dogBreeds.katShortDesc, dbo.BREED_dogBreeds.longDesc, dbo.BREED_dogBreeds.katLongDesc,
dbo.BREED_dogBreeds.thingsToConsider, dbo.BREED_dogBreeds.temperament, dbo.BREED_dogBreeds.history, dbo.BREED_dogBreeds.feeding,
dbo.BREED_tblCountry.Country_Name, dbo.BREED_dogBreeds.colour, dbo.BREED_dogBreeds.breedProfileLink, dbo.BREED_Grooming.groomText,
dbo.BREED_GroomFrequencyValues.value, dbo.BREED_Training.intelligence, dbo.BREED_Training.trainingNotes, dbo.BREED_Training.exerciseText,
dbo.BREED_Training.exerciseTime, dbo.BREED_Training.timePerDay, dbo.BREED_Suitability.idealOwner, dbo.BREED_Size.size,
dbo.BREED_sizes.bheightmin, dbo.BREED_sizes.bheightmax, dbo.BREED_sizes.bweightmin, dbo.BREED_sizes.bweightmax,
dbo.BREED_sizes.dheightmin, dbo.BREED_sizes.dheightmax, dbo.BREED_sizes.dweightmin, dbo.BREED_sizes.dweightmax,
dbo.BREED_Sociability.compatibility FROM dbo.BREED_Sociability RIGHT OUTER JOIN
dbo.BREED_dogBreeds ON dbo.BREED_Sociability.sociabilityID = dbo.BREED_dogBreeds.sociabilityID LEFT OUTER JOIN
dbo.BREED_Size RIGHT OUTER JOIN
dbo.BREED_sizes ON dbo.BREED_Size.id = dbo.BREED_sizes.sizeid ON
dbo.BREED_dogBreeds.sizeId = dbo.BREED_sizes.breedSizeId LEFT OUTER JOIN
dbo.BREED_Suitability ON dbo.BREED_dogBreeds.suitabilityID = dbo.BREED_Suitability.suitabilityID LEFT OUTER JOIN
dbo.BREED_Training ON dbo.BREED_dogBreeds.trainID = dbo.BREED_Training.trainID LEFT OUTER JOIN
dbo.BREED_GroomFrequencyValues RIGHT OUTER JOIN
dbo.BREED_Grooming ON dbo.BREED_GroomFrequencyValues.gfvID = dbo.BREED_Grooming.gfvID ON
dbo.BREED_dogBreeds.groomID = dbo.BREED_Grooming.groomID LEFT OUTER JOIN
dbo.BREED_tblCountry ON dbo.BREED_dogBreeds.country = dbo.BREED_tblCountry.Country_ID

Table 2:
SELECT [breedId]
,[breedCriteriaID]
,[value]
,[icon]
FROM [v1vw1n_dogmatch].[dbo].[vbreedCriterias]
where levelID>=3
order by breedId, breedCriteriaID asc

TABLE 3
SELECT [breedCriteriaID]
,[criteriaValue]
,[icon]
FROM [v1vw1n_dogmatch].[dbo].[BREED_Criteria]

Table1
186Afghan HoundTazi, Baluchi HoundA strikingly beautiful dog with dignified poise.Afghans are kept primarily as show dogs and can also be used for lure coursing. They are extremely loving and loyal to their owners and are gentle souled and good with children. Afghans can make companion dogs but their considerable needs means that only devoted owners keep them. Aloof with strangers but affectionate and loyal to their owners. Can be very clown like at play and are very people oriented. Love children and being included in family life. Can become introverted if excluded from social situations whilst pups.An ancient breed, the afghan looks as classy as its pedigree. Afghans were used in Afghanistan to protect the flocks and would hunt and kill panthers, leopards and other large predators. The first dog to be shown was in the UK in 1907 having previously been banned from export. Afghans can be fussy with their food and it is better to instill good eating habits when they are pups and ideally treats should be avoided. AfghanistanAfghans are a grooming salons dream come true - they demand regular grooming and can quickly become knotted and tangled without it. DailyAll dogs are bright but Afghans may not quite earn the MENSA of the dog world.Afghans can be hard to train with lots of perseverance needed. Highly strung, stubborn and sensitive natured dog making them difficult to train. Training cannot be rushed and as they are sensitive souls and it is very important not treat them harshly. Sometimes difficult to housebreak. As puppies, Afghans often appear awkward, with uneven growth, gawkiness and loose limbs, and for this reason, exercise must be carefully monitored to avoid injury to their growing bones.00Suitable for the experienced, comitted dog owner with time on their hands and a great love for the breed.large63cm69cm23kg25kg68cm74cm25kg (55lb)28kg (62lb)They are hunting stock and love to chase anything that moves so perhaps not the ideal dog to share a home with cats and small animals!
187Bluetick CoonhoundNULLNot found in Australia, the Bluetick Coonhound is a friendly hound that makes an excellent tracking or scent dog.NULLThis breed originated in the states and has a smooth, dense, tri colour coat. The base colour is white with heavy ticking of black and tan markings over their chest, eyes, muzzle, lower legs and feet. This breed is recognised as a competitive, fearless, dedicated hunter. The Bluetick has a typical hound bawl and so is not the quietest of dogs.NULLThis dog needs a lot of exercise. They love to do jobs, and keep busy. They need to be exercised vigorously or they run the danger of becoming destructive and will howl excessivly.The Coonhound is deeply devoted, fearless, attentive and loyal. They make very good guardians and family companions. They are reserved with strangers, but are not aggressive towards them. They are not the best with other animals, and get along better with older, considerate children.The Bluetick originated in Louisiana at the beginning of the 20th century. They were developed from crosses between the English Coonhound, the Foxhound and the french Grand Bleu de Gascogne. Their tricoloured, blue-speckled coat sets them apart from other Coonhound breeds. Originally they were registered as a variant of the English Coonhound, but in 1946 they were given separate recognition as a distinct breed in their own right.Today the English Coonhound is sometimes referred to as the Redtick. The original, old-fashioned Bluetick dog, which was larger and slower than the modern type, began to loose ground because they did less well in the increasingly popular field competitions and night trials. The smaller, faster version began to eclipse them and became one of the most popular and numerous of all coonhound breeds. This upset the traditionalists, who preferred the old-style Big Blue , and some of them reacted by switching their allegiance to other large-bodied breeds, such as the Blue Gascon, and the Majestic.This breed is not fussy when it comes to their diet, but they have quite a healthy appetite.United States of AmericaNULLNULLNULLNULLNULLNULLNULLNULLNULLNULLNULLNULLNULLNULLNULLNULLNULLNULLNULLNULL
188Australian Cattle DogCattledog, Queensland Heeler, Heeler, Blue Heeler, Red Heeler, BlueyA strong compact working dog, the Australian Cattle Dog is one of the most popular breeds of dog in Australia.A strong compact working dog, the Australian Cattle Dog is one of the most popular breeds of dog in Australia.The Australian Cattle Dog is a strong compact working dog with a combination of substance, power, balance and hard muscular condition that conveys the impression of great agility, strength and endurance with the ability and willingness to carry out his allotted task however arduous. His head is wedge shaped with a broad skull and muscular cheeks and oval shaped, dark brown eyes that express alertness and intelligence and have a warning or suspicious glint when approached by strangers. His ears are broad at base, muscular, pricked and moderately pointed. His rain resistant coat is a smooth double coat with a close, hard outer coat and a short dense undercoat AND comes in two colours: Blue: Blue, blue-mottled or blue speckled with tan markings. Red: An even red speckle all over, including the undercoat, with or without darker red markings on the head. The pups are born white, developing their colour gradually from approximately three weeks of age. The Australian Cattle Dog is a strong compact working dog with a combination of substance, power, balance and hard muscular condition that conveys the impression of great agility, strength and endurance with the ability and willingness to carry out his allotted task however arduous. His head is wedge shaped with a broad skull and muscular cheeks and oval shaped, dark brown eyes that express alertness and intelligence and have a warning or suspicious glint when approached by strangers. His ears are broad at base, muscular, pricked and moderately pointed. His rain resistant coat is a smooth double coat with a close, hard outer coat and a short dense undercoat AND comes in two colours: Blue: Blue, blue-mottled or blue speckled with tan markings. Red: An even red speckle all over, including the undercoat, with or without darker red markings on the head. The pups are born white, developing their colour gradually from approximately three weeks of age. The Australian Cattle Dog has a strong herding instinct and when playing may nip the heels of children.The Australian Cattle Dog needs a job, companionship and activity for the mind and body, all day, every day. Easily bored, he can become noisy and/or destructive. Renowned for his protectiveness and loyalty to master and property, he is very selective as to who is friend or foe. In 1840, Thomas Hall, a landowner in New South Wales, imported two smooth-haired blue merle Scotch Collies and crossed their progeny with the Dingo. The resulting litters became known as Hall's Heelers. The progeny were generally of Dingo type with the colour being either red or blue merle and were valued for their ability to handle wild cattle, stamina to travel great distances over all types of terrain, and their endurance in extremes of temperature. Later, Hall's Heelers were crossed with a Dalmatian, which changed the merle colour to red or blue speckle and instilled in the dogs a love of horses and protectiveness toward master and property. A further cross was made to the Kelpie to produce highly intelligent, controllable workers resembling thickset Dingoes and with peculiar markings known to no other dog. In 1903 a standard for the breed was drawn up and from these beginnings the Australian Cattle Dog has developed into one of the most popular breeds of dog in Australia today. AustraliaMinimal grooming although weekly brushing is required to remove dead hair. Does shed seasonally.Weekly - at homeHe is loving, playful, and eager to please his owner. Very quick to learn.Unless you can give him extensive exercise do not even consider owning an Australian Cattle Dog. He was bred to work all day in hard conditions and will become bored if not given sufficient exercise.602Single guy or gal, athletic, able to have the dog with them most of the time. Not a first time dog owner. Families with older children.medium43cm (17")48cm (19")16kg (35lb)20kg (44lb)46cm (18")51cm (20")16kg (35lb)20kg (44lbs)Not good with dogs of the same sex. OK with cats if raised with the cat since puppyhood. Not good with other small mammals.

TABLE 2
1861suits older children/Images/icons/older_children.gif
1862suits younger children/Images/icons/suits_young_children.gif
1863suits elderly/disabled. Not too boisterous/Images/icons/suits_elderly_disabled.gif
1866easy to transport/Images/icons/transport.gif
1868grooming needs/Images/icons/grooming_needs.gif
18610distress/destruction when left alone/Images/icons/distressed_when_alone.gif
18612Shedding / Hair loss/Images/icons/shedding_hairloss.gif
18615Energy Level/Images/icons/energy_levels.gif
18616Affection with family/Images/icons/affectionate.gif
18622may bite intruder/Images/icons/bite_intruder.gif
18623watchdog skills/Images/icons/watchdog_skills.gif
1871suits older children/Images/icons/older_children.gif
1876easy to transport/Images/icons/transport.gif
18710distress/destruction when left alone/Images/icons/distressed_when_alone.gif
18712Shedding / Hair loss/Images/icons/shedding_hairloss.gif
18713stranger friendly/Images/icons/stranger_friendly.gif
18715Energy Level/Images/icons/energy_levels.gif
18716Affection with family/Images/icons/affectionate.gif
18722may bite intruder/Images/icons/bite_intruder.gif
18723watchdog skills/Images/icons/watchdog_skills.gif
1881suits older children/Images/icons/older_children.gif
1883suits elderly/disabled. Not too boisterous/Images/icons/suits_elderly_disabled.gif
1884cattle friendly/Images/icons/cattle_friendly.gif
1886easy to transport/Images/icons/transport.gif
18810distress/destruction when left alone/Images/icons/distressed_when_alone.gif
18811trainability/Images/icons/trainable.gif
18812Shedding / Hair loss/Images/icons/shedding_hairloss.gif
18813stranger friendly/Images/icons/stranger_friendly.gif
18814How often this breed is found in the pound/Images/icons/found_in_pount.gif
18815Energy Level/Images/icons/energy_levels.gif
18816Affection with family/Images/icons/affectionate.gif
18819Availability/Images/icons/availability.gif
18820cat friendly/Images/icons/cat_friendly.gif
18822may bite intruder/Images/icons/bite_intruder.gif
18823watchdog skills/Images/icons/watchdog_skills.gif
1891suits older children/Images/icons/older_children.gif
1892suits younger children/Images/icons/suits_young_children.gif
1898grooming needs/Images/icons/grooming_needs.gif
18910distress/destruction when left alone/Images/icons/distressed_when_alone.gif
18912Shedding / Hair loss/Images/icons/shedding_hairloss.gif
18913stranger friendly/Images/icons/stranger_friendly.gif
18914How often this breed is found in the pound/Images/icons/found_in_pount.gif
18915Energy Level/Images/icons/energy_levels.gif
18916Affection with family/Images/icons/affectionate.gif
18919Availability/Images/icons/availability.gif
18923watchdog skills/Images/icons/watchdog_skills.gif
1901suits older children/Images/icons/older_children.gif
1903suits elderly/disabled. Not too boisterous/Images/icons/suits_elderly_disabled.gif
1906easy to transport/Images/icons/transport.gif
19010distress/destruction when left alone/Images/icons/distressed_when_alone.gif
19011trainability/Images/icons/trainable.gif
19013stranger friendly/Images/icons/stranger_friendly.gif
19014How often this breed is found in the pound/Images/icons/found_in_pount.gif
19015Energy Level/Images/icons/energy_levels.gif
19016Affection with family/Images/icons/affectionate.gif
19019Availability/Images/icons/availability.gif
19022may bite intruder/Images/icons/bite_intruder.gif
19023watchdog skills/Images/icons/watchdog_skills.gif
19024Gay Icon/Images/icons/gay_icon.gif
1921suits older children/Images/icons/older_children.gif
1922suits younger children/Images/icons/suits_young_children.gif
1923suits elderly/disabled. Not too boisterous/Images/icons/suits_elderly_disabled.gif
1924cattle friendly/Images/icons/cattle_friendly.gif
1925bunny/guinea pig friendly/Images/icons/bunny_friendly.gif
1926easy to transport/Images/icons/transport.gif
19210distress/destruction when left alone/Images/icons/distressed_when_alone.gif
19211trainability/Images/icons/trainable.gif
19212Shedding / Hair loss/Images/icons/shedding_hairloss.gif
19213stranger friendly/Images/icons/stranger_friendly.gif
19215Energy Level/Images/icons/energy_levels.gif
19216Affection with family/Images/icons/affectionate.gif
19217dog friendly/Images/icons/dog_friendly.gif
19219Availability/Images/icons/availability.gif
19220cat friendly/Images/icons/cat_friendly.gif
19223watchdog skills/Images/icons/watchdog_skills.gif

etcHi there

I got a response on another board. Basically I just used
SELECT dogBreedID,
crit1value = MIN(CASE criteriaID WHEN 1 THEN value END),
crit1location = MIN(CASE criteriaID WHEN 1 THEN location END),
crit2value = MIN(CASE criteriaID WHEN 2 THEN value END),
crit2location = MIN(CASE criteriaID WHEN 2 THEN location END),
...
FROM tbl
GROUP BY dogBreedID

and joined that to the first table.

Fantastic!