Showing posts with label stored. Show all posts
Showing posts with label stored. Show all posts

Monday, March 26, 2012

Joins query help

Hi all,

Just after some help with a query (Stored Procedure) I've managed to get wrapped round my head.

The DB is as such:

COMPANY
Company_id
Company_name

COMPANY_GROUP
Group_id
Group_name

USER
User_id
User_name

Bridging tables

COMPANY_GROUP_BRIDGE
company_id
group_id

USER_COMPANY_BRIDGE
user_id
company_id

Basically, the only parameter I have for the query is a User_id.

I need to get the Group linked to the User and return all the companies within that group.

I'vetried reading up on all the join types again but have just got thiscompletely wrapped round my neck. I keep thinking along the lines ofSELECT all the companies linked to all the groups linked to all thecompanies linked to the User_id :s I must be able to dothis without using two Company tables...?

Any help much appreciated,

Pete

I don't think the table structure is good. You only need one bridge table in stead of two. In this one table, just put company_id, group_id, and user_id together. Otherwise, you will join too much.

|||

There seems to be a contradiction here. You wrote

"I need to get the Group linked to the User and return all the companies within that group."

But you don't have any table that stores the users assigned to a company group.

In case a user belongs to a group and not a company, create a table that will store user id and group id.

Then you can write a query to get all the companies linked to the group to which the user belongs

|||

Cheers for the replies guys, you've pretty much asserted what I've been dreading all along.

The DB is a complete messed up and looks like I'm gonna have to completely overhaul it :/

(BTW:It is not currently possible for a user to be linked to a group but nota company. The groups are not in there for this purpose - In fact Imnot sure why there are there!)

|||

Hmm OK,

Any reccomendations on what a DB 'should' look like based on thisveryextremely light spec:

A Distributor can have many Resellers
A Reseller can have many Groups
A Group can have many Companies
A Company can have many Users
A User may belong to many Companies

(Looking at it - it has been designed so that a Company can belong to many Groups but I dont think that would ever happen )

I think the problem originally was that a User may belong to certaincompanies within a group but not neccessarilly all of them - hence theUser is linked to individual companies rather than a Group.

Also, in the admin backend the problem is which companies to show for options such as edit etc.

A Group Administrator may see all the companies within a group but aCompany Administrator may only see the Companies they are associatedwith in the bridge table. Looks like I'll need the User's'access_level' in all the SProcs.

OK, back to basics. My head hurts.

|||

It is often helpful to think about it this way: every noun is a table, so:

Distributor table
Reseller table
Group table
Company table
User tables

A Distributor can have many Resellers
A Reseller can have many Groups
A Group can have many Companies
A Company can have many Users
A User may belong to many Companies

Every time you write, "can have many" it implies the presence of a foreign key (FK). Many-to-many relationships (company-user) requires a cross reference table. So:

Distributor table
- Distributor ID (probably an identity column)
- Reseller ID (FK to Reseller table)
- other fields

Reseller table
- Reseller ID (probably an identity column)
- Group ID (FK to Group table)
- other fields

Group Table
- Group ID (probably an identity column)
- Company ID (FK to Company table)
- other fields

Company Table
- Company ID (probably an identity column)
- other fields

User Table
- User ID (probably an identity column)
- other fields

Company-User-Cross-Reference Table
- Company ID (FK to Company table)
- User Id (FK to User Table)
NOTE: The Primay Key of this table is Company ID + User ID

|||

Hi David, thanks for that!

That does reassure me that I am on the right track with my structure as that is the way I have gone about things.

I think I rushed into it though and ended up creating astructure where a group could belong to multiple resellers which iswrong (and also that resellers could belong to multiple Distributorswhich is also wrong) So I shall remove the cross-reference tables forDistributors and Resellers.

However, I think I need to make the following minor changes to your suggestion:

Group Table
- Group ID (probably an identity column)
- other fields

Company Table
- Company ID (probably an identity column)
- Group ID (FK to Group table)
- other fields

This is so that a Group can have many Companies. (and a Company can only belong to one group)

(And also changes so Reseller Table contains the DistributorID and the Group table contains the ResellerID)

Could you just clear something up for me though please: Youappear to have placed the CompanyID in the Group table - would this notmean that a Group can only have one company? Is it not correct to putthe GroupID in the Company table. Then each Company can be linked to aparticular group?

What do you think..?

Again, thanks for your advice it is greatly appreciated,

Pete

|||

pete_m:

Could you just clear something up for me though please: You appear to have placed the CompanyID in the Group table - would this not mean that a Group can only have one company? Is it not correct to put the GroupID in the Company table. Then each Company can be linked to a particular group?

Yes, you're right, I was doing this too fast. I think you have the idea now.

Monday, March 19, 2012

joining sysprocesses with fn_get_sql

ok, I have a requirement where I need to get a list of sql commands currently being blocked.
This is very easy to do via stored procedure, and I have it working well using a vb.net console app to fire it off.

Trouble is, I need to ship it to different offices on an ad hoc basis. I don't want to install a stored procedure on each site because it'll be a one off job and there is not likely to be anyone available who would know how to even install a new sp. So, I thought I'd try and pull back the sql commands via a select statement, joining together sysprocesses and the fn_get_sql udf. This returns a table, so I presumed I could join the two together using a subquery via the sql_handle with something like this :

SELECT sql_handle,
(
SELECT top 1 [text] FROM ::fn_get_sql(sysprocesses.sql_handle)
) as sqlcommand

FROM master..sysprocesses

The error back is incorrect syntax near 'sysprocesses'. I can't see if I'm doing anything obvious wrong.

Anyone any ideas? I'm using SQL Server 2000 sp3.A BOL example for using fn_get_sql:
DECLARE @.Handle binary(20)SELECT @.Handle = sql_handle FROM sysprocesses WHERE spid = 52SELECT * FROM ::fn_get_sql(@.Handle) HTH|||thanks for your reply, however, that will only work in a stored procedure.
I won't be able to install a sp, as it needs to be completely standalone.
I'm trying to find a one-hit SQL query to do the job. It should work, but it doesn't.

cheers,

Joining Rows in a SubQuery

I have the following code in a stored procedure
SELECT CatID, ParentId, CategoryName, (select count(*)
from members WHERE DirectoryCat = DirectoryCats.CatID and
InFreeDirectory=1 and ApproveDirectory=1) pagecount
FROM DirectoryCats
where active=1
order by CategoryName
it's output is similar to this:
CatID | ParentId | CategoryName | pagecount
6 1 Cat1 0
4 Null Cat2 3
I would like to make a new column (say Newtext) adn Return something like th
is
CatID | ParentId | CategoryName | pagecount | NewText
6 1 Cat1 0 Cat1 (0)
4 Null Cat2 3 Cat2 (3)
How can i join the data to have this result?
I would hope that i could do something like CategoryName + "(" + pagecount +
")" in some sort of sql statement.
Thanks for any input
Lots of ways, here's one
SELECT CatID, ParentId, CategoryName,pagecount ,
CategoryName + '(' + cast(pagecount as varchar(10))+ ')' as
NewText
FROM
(
SELECT CatID, ParentId, CategoryName, (select count(*)
from members WHERE DirectoryCat = DirectoryCats.CatID and
InFreeDirectory=1 and ApproveDirectory=1) pagecount
FROM DirectoryCats
where active=1
) X
order by CategoryName|||One approach is to use a derived table, embedding the existing query
in the FROM clause of an outer query:
SELECT *,
NewText =
CategoryName + '(' + convert(varchar(8),pagecount) + ')'
FROM (<query as you stated it> ) as X
Roy Harvey
Beacon Falls, CT
On Thu, 27 Apr 2006 13:37:02 -0700, Fabuloussites
<Fabuloussites@.discussions.microsoft.com> wrote:

>I have the following code in a stored procedure
>SELECT CatID, ParentId, CategoryName, (select count(*)
>from members WHERE DirectoryCat = DirectoryCats.CatID and
>InFreeDirectory=1 and ApproveDirectory=1) pagecount
>FROM DirectoryCats
>where active=1
>order by CategoryName
>
>it's output is similar to this:
>CatID | ParentId | CategoryName | pagecount
>6 1 Cat1 0
>4 Null Cat2 3
>I would like to make a new column (say Newtext) adn Return something like t
his
>CatID | ParentId | CategoryName | pagecount | NewText
>6 1 Cat1 0 Cat1 (0)
>4 Null Cat2 3 Cat2 (3)
>How can i join the data to have this result?
>I would hope that i could do something like CategoryName + "(" + pagecount
+
>")" in some sort of sql statement.
>Thanks for any input|||thanks for the fast and helpful response.
"markc600@.hotmail.com" wrote:

>
> Lots of ways, here's one
>
> SELECT CatID, ParentId, CategoryName,pagecount ,
> CategoryName + '(' + cast(pagecount as varchar(10))+ ')' as
> NewText
> FROM
> (
> SELECT CatID, ParentId, CategoryName, (select count(*)
> from members WHERE DirectoryCat = DirectoryCats.CatID and
> InFreeDirectory=1 and ApproveDirectory=1) pagecount
> FROM DirectoryCats
> where active=1
> ) X
> order by CategoryName
>|||thanks for the fast and helpful response.
"Roy Harvey" wrote:

> One approach is to use a derived table, embedding the existing query
> in the FROM clause of an outer query:
> SELECT *,
> NewText =
> CategoryName + '(' + convert(varchar(8),pagecount) + ')'
> FROM (<query as you stated it> ) as X
> Roy Harvey
> Beacon Falls, CT
>
> On Thu, 27 Apr 2006 13:37:02 -0700, Fabuloussites
> <Fabuloussites@.discussions.microsoft.com> wrote:
>
>

Joining one database table with other database table in stroed procedures.

Hi All,
I need to perform a join on table1 of database1 with table2 or database2, in a stored procedure and return to my web application.. For this I'm providing execute permission on stored procedure, in database1 and "SELECT" permission on database2 table 2, to my database webuser.
Is there any way ( Another stored procedure in database2), i can get join on two tables without SELECT permission right on table2 ( or table1).
Purely using stored procedures. If so how?Normally you only need to grant execute permission on a stored procedure not select permission on the underlying tables.

Past that I would setup a sp to on database1 to return the data and make sure the webuser has an a security path from database1 to database2. How do yo uhave security setup for this user on databse1 and database2?|||Hi Paul,
Thanks, What is meant by security path? I didnot get ur point.
User have only public permission on both databases. Is it not enough? I do have execute permission on sp1 (Stored Procedure) in database1.
but in sp1 I have a select statement which is a join on database2 table-'table2'. When I tried to execute sp1 from web application only with execute permission on sp1-
I got an error as Webuser does not have 'SELECT' permission on table2 of database2. So I provided it and sp1 worked fine. But I don't want to use a SELECT permission- What is alternate, for the join.
sp1 has simple
SELECT *
FROM database1.dbo.table1 t1
INNER JOIN database2.dbo.table2 t2
ON (t1.col1 = t2.col1)

Originally posted by Paul Young
Normally you only need to grant execute permission on a stored procedure not select permission on the underlying tables.

Past that I would setup a sp to on database1 to return the data and make sure the webuser has an a security path from database1 to database2. How do yo uhave security setup for this user on databse1 and database2?|||by security path I was refering to how a user gets authenticated on server2 when making a connection from server1.

You might try using OPENQUERY to call a stored procedure on server2 and use the results to join to a table on server1. I haven't had the need for this in the past so I am working on theory here. Check BOL for usage on OPENQUERY, they have some good examples.|||When calling a stored proc from database 1, you need execute privs on the proc. You do not need to give the user privs on the table itself as long as it is in database 1, too. If database 2 is owned by the same user that is the owner of database 1, you do not need explicit permissions on the object in table 2 accessed by the proc. However, if the database owners are different for the two databases, the user calling the proc must have explicit permissions in the second database.

If need be, you can change the database owner by:

EXEC sp_changedbowner 'username'

Execute this in the database you want to change.|||Well Both databases are on same server. Is OPENQUERY solve in this case too?|||Originally posted by soumyag
Well Both databases are on same server.

It doesn't matter what server they are on, the owner of the databases is what matters. You can have multiple databases on the same server with different owners. In query analyzer, run:

sp_helpdb

It will list the owner for each of the databases. If the owner is different, run sp_changedbowner to set them the same.|||Hi,
Both are on same server, but owned by different users. And I don't have any right to change the dbowners But how it will help in writing a join on tables. What is other alternative way to solve this problem.
Thanks.

Originally posted by bglass

It doesn't matter what server they are on, the owner of the databases is what matters. You can have multiple databases on the same server with different owners. In query analyzer, run:

sp_helpdb

It will list the owner for each of the databases. If the owner is different, run sp_changedbowner to set them the same.

Joining on NULLS

I have a stored proc that matches 2 tables on a datetime column. I am
worried that matching on a NULL column is not a good idea. Should I consider
matching on a ISNULL(datecolumn1,0) = ISNULL(datecolumn2,0) a better idea?
Thanks.
DavidI believe outer joins should take care of this.
"David Chase" <dlchase@.lifetimeinc.com> wrote in message
news:%23GBhm7xCGHA.3812@.TK2MSFTNGP15.phx.gbl...
>I have a stored proc that matches 2 tables on a datetime column. I am
>worried that matching on a NULL column is not a good idea. Should I
>consider matching on a ISNULL(datecolumn1,0) = ISNULL(datecolumn2,0) a
>better idea? Thanks.
> David
>|||> worried that matching on a NULL column is not a good idea. Should I
> consider matching on a ISNULL(datecolumn1,0) = ISNULL(datecolumn2,0) a
> better idea?
Does this mean that you intended to match NULLs (i.e., you consider NULL =
NULL to be true)? If so, then your logic is dependent on the current
ANSI_NULLS setting. There is a section in BOL (sigh - as there usually is)
that discusses this particular issue - Accessing and Changing Relational
Data / Query Fundamentals / Filtering Rows with WHERE and HAVING / NULL
Comparison Search Conditions.
As for whether this (or any other approach) is "better" depends on many
factors. A connection setting dependency is generally not recommended.
Your "better" approach is dependent on knowledge of the domain of the
columns - is this dependency any "better" than the connection setting? I'll
ignore the use of the implicit conversion, something that can easily trip an
unsuspecting reader.
The short answer is that it IS better to use a more defensive approach to
coding. However, this particular case will also involve the identification
of a technique that yields the best performance for your given situation.
Performance is often driven as much by the batch characteristics (e.g., use
of parameters, plan usage) as it is by the query and schema. Logically, you
should use something like:
where (col1 = col2) or (col1 is null and col2 is null)
Isnull and coalesce can be used - as you indicated. There might also be
other ways of looking at the data that would lead you to a different
approach. If you are attempting to equate NULLs, perhaps this is an
indication of a flaw in the data model. If so, the "better" approach is to
find and fix this model flaw. A better model generally improves the system
as a whole, often by orders of magnitude.|||not sure what you mean:
"matching on a null column" to me means "null = null" - if that's your
meaning, then isnull(datecolumn1,0)=isnull(datecolumn2
,0) is the same thing.
yes - joining on nulls is a bad idea -- if the other join criteria (if
any) isn't selective enough, then you'll get a cartesian product for
these (x nulls in table1 * x nulls in table2).
why would you want to match them?
David Chase wrote:
> I have a stored proc that matches 2 tables on a datetime column. I am
> worried that matching on a NULL column is not a good idea. Should I consid
er
> matching on a ISNULL(datecolumn1,0) = ISNULL(datecolumn2,0) a better idea?
> Thanks.
> David
>|||clarification: by "null = null" i mean that these would "match", not
that you would use "where null = null".
"null = null" evaluates to null unless SET ANSI_NULLS is OFF.
therefore, these would not be included in the results, whereas
isnull(datecolumn1,0)=isnull(datecolumn2
,0) would be included in the
results regardless of ANSI_NULLS setting.
but the end result in the narrative is the same - consider nulls a match
and return them in the result set.
Trey Walpole wrote:
> not sure what you mean:
> "matching on a null column" to me means "null = null" - if that's your
> meaning, then isnull(datecolumn1,0)=isnull(datecolumn2
,0) is the same
> thing.
> yes - joining on nulls is a bad idea -- if the other join criteria (if
> any) isn't selective enough, then you'll get a cartesian product for
> these (x nulls in table1 * x nulls in table2).
> why would you want to match them?
> David Chase wrote:
>|||> "null = null" evaluates to null unless SET ANSI_NULLS is OFF.
Not for a JOIN operation, though. ANSI_NULLS does not change the meaning of
NULL = NULL for a join,
the unknown will still be false in the end:
USE tempdb
CREATE TABLE t1(c1 datetime, c2 int)
CREATE TABLE t2(c1 datetime, c2 int)
INSERT INTO t1 VALUES(NULL, 1)
INSERT INTO t2 VALUES(NULL, 3)
INSERT INTO t1 VALUES('20050101', 2)
INSERT INTO t2 VALUES('20050101', 4)
INSERT INTO t1 VALUES('20050102', 5)
INSERT INTO t2 VALUES('20050103', 6)
SELECT * FROM t1
SELECT * FROM t2
SET ANSI_NULLS OFF
SELECT *
FROM t1
INNER JOIN t2 ON t1.c1 = t2.c1
SELECT *
FROM t1 ,t2
WHERE t1.c1 = t2.c1
Tibor Karaszi, SQL Server MVP
http://www.karaszi.com/sqlserver/default.asp
http://www.solidqualitylearning.com/
Blog: http://solidqualitylearning.com/blogs/tibor/
"Trey Walpole" <treypole@.newsgroups.nospam> wrote in message
news:ejF54IzCGHA.2040@.TK2MSFTNGP14.phx.gbl...
> clarification: by "null = null" i mean that these would "match", not that
you would use "where
> null = null".
> "null = null" evaluates to null unless SET ANSI_NULLS is OFF.
> therefore, these would not be included in the results, whereas
> isnull(datecolumn1,0)=isnull(datecolumn2
,0) would be included in the resu
lts regardless of
> ANSI_NULLS setting.
> but the end result in the narrative is the same - consider nulls a match a
nd return them in the
> result set.
>
> Trey Walpole wrote:|||ah yes - thanks for the clarification
Tibor Karaszi wrote:
>
> Not for a JOIN operation, though. ANSI_NULLS does not change the meaning
> of NULL = NULL for a join, the unknown will still be false in the end:
> USE tempdb
> CREATE TABLE t1(c1 datetime, c2 int)
> CREATE TABLE t2(c1 datetime, c2 int)
> INSERT INTO t1 VALUES(NULL, 1)
> INSERT INTO t2 VALUES(NULL, 3)
> INSERT INTO t1 VALUES('20050101', 2)
> INSERT INTO t2 VALUES('20050101', 4)
> INSERT INTO t1 VALUES('20050102', 5)
> INSERT INTO t2 VALUES('20050103', 6)
> SELECT * FROM t1
> SELECT * FROM t2
> SET ANSI_NULLS OFF
> SELECT *
> FROM t1
> INNER JOIN t2 ON t1.c1 = t2.c1
> SELECT *
> FROM t1 ,t2
> WHERE t1.c1 = t2.c1
>

Joining MS SqlServer data with Oracle data

OK so there is some data in an Oracle DB that I need to query and analyze. Unfortunately, the criteria for selecting/grouping the data is stored in a MS Sql Server DB. This cannot be changed.

SqlServer
Group Name ID# Item Condition
AAA123 1 a 1
AAA123 2 a 1
AAA123 3 a 1
AAA123 4 a 2
AAA123 5 a 2
AAA123 1 b 3
AAA123 2 b 4
AAA123 3 b 3
AAA123 4 b 4
AAA123 5 b 3
BBB123 1 a 1
BBB123 2 a 1
BBB123 3 a 2
BBB123 4 a 2
BBB123 5 a 2

Oracle
Group Name ID# Value
AAA123 1 50%
AAA123 2 55%
AAA123 3 60%
AAA123 4 80%
AAA123 5 70%
BBB123 1 35%
BBB123 2 45%
BBB123 3 50%
BBB123 4 50%
BBB123 5 80%

I need to be able to get this:
Group Name Item Condition Value
AAA123 a 1 55%
AAA123 a 2 75%
AAA123 b 3 60%
AAA123 b 4 67.5%
BBB123 a 1 40%
BBB123 a 2 60%

Any idea how I can get the data from these two DBs to talk to each other? Thanks.

You should either import the data from Oracle into some temp table in SQL Server and work from SQL Server or the otherway. You need to choose the host first.

|||

That sounds great!

Can anyone help me understand how to import data from an Oracle DB into a temp table in SqlServer?

Thanks.

|||

Check out the DTS Import/Export wizard via Tools -> Data Transformation Services in Enterprise Manager.

|||

Unfortunately, I don't have enterprise... I tried using the linkedtable stored procedure but I don't have permissions on the Oracle Table, and I will not be granted them. Is there another way to import the data which does not require anything but SELECT priviledges (read-only account) where I can accomplish this using SqlServer Mgmt Studio Express? Thanks again.

-steve

|||

Check out OPENQUERY operator in books online.

|||

OPENQUERY operates on linked tables. Unfortunately, I cannot use this as a linked table because my account does not have permissions to access the sp_addlinkedtable stored procedure.

Does anyone know how I can do this without using linked tables? I can pull the data by connecting directly to the oracle DB (I have an account I can use SELECT with) but I need to use information stored in the SQL Server Table.

Is there some way I can use datatables in asp.net to do this, rather than transact SQL wihin the actual database? Thanks.

Monday, March 12, 2012

Joining datasets returned from stored procedures.

Hello,
I am restricted to using stored procedures for data access. I would like to
be able to create a "Text" Dataset named C which is a join of two "Stored
Procedure" data sets (sp1, and sp2). Any idea how I can do this. Thanks.Tyr this:
SELECT * FROM OPENQUERY(servername, 'sp_1')
union
SELECT * FROM OPENQUERY(servername, 'sp_2')
Ravi Mumulla (Microsoft)
SQL Server Reporting Services
This posting is provided "AS IS" with no warranties, and confers no rights.
"Jason Agee" <jason.agee@.tlc.state.tx.us> wrote in message
news:%23%23nvqx4YEHA.1448@.TK2MSFTNGP12.phx.gbl...
> Hello,
> I am restricted to using stored procedures for data access. I would like
to
> be able to create a "Text" Dataset named C which is a join of two "Stored
> Procedure" data sets (sp1, and sp2). Any idea how I can do this. Thanks.
>

Friday, March 9, 2012

Join with Stored Procedure?

I have a stored procedure A that returns results in this format:

ID
--
1
2
...

I want to make a procedure B that, by joining with the result obtained from A (A INNER JOIN B on A.ID = B.ID), returns a table like this:

ID Title
---
1 Title 1
2 Title 2

But SQL server says invalid object name for A when I try to run B... Assuming stored procedures cannot be "joined", what can I do to obtain similar results?My understanding is that you dont need the first sp. Try this:

Select b.id, b.name where b.id in (select a.id from a)

(Ever tried Select b.id, b.name where b.id in (exec a))

- OR -

Change the type of your first stored procedure to a function that returns table. See help or ask a guru. Then you will (hopefully) be able to do things such as:

select * from a() inner join b on a().id = b.id|||Thanks, using function solved the problem :)

Wednesday, March 7, 2012

Join the Result of xp_logininfo with a table

Hello group!

i have a table "group_code" wich relates the names of
nt-(domain)-groups to codes. now i want use the stored procedure
xp_logininfo (asking for the group-membership of the current user) to
join the result to "group_code". then i must use the new result (the
code) to join against other tables.

i know now, that i cant join results of SPs against tables. may be that
a UDF with a table result is the correct approach. but i have no idea
how to wrap the xp_logininfo in a UDF.

a other way can be to do in a UDF the same thing like the xp_logininfo.
then this UDF should deliver at least the nt-(domain)-groups in wich
the current-user is a member.

Is there anybody who can give me the code for that?
many thanx in advance.

Karl(Karl.Auer@.gmail.com) writes:
> i have a table "group_code" wich relates the names of
> nt-(domain)-groups to codes. now i want use the stored procedure
> xp_logininfo (asking for the group-membership of the current user) to
> join the result to "group_code". then i must use the new result (the
> code) to join against other tables.
> i know now, that i cant join results of SPs against tables. may be that
> a UDF with a table result is the correct approach. but i have no idea
> how to wrap the xp_logininfo in a UDF.
> a other way can be to do in a UDF the same thing like the xp_logininfo.
> then this UDF should deliver at least the nt-(domain)-groups in wich
> the current-user is a member.

I don't think you can do this with a UDF. You can do:

CREATE TABLE #temp (...)
INSERT #temp (...)
EXEC master..xp_logininfo

But you cannot do this in a UDF, since you cannot create temp
tables in a UDF, and you cannot do INSERT EXEC on a table variable
if memory serves.

As for how #temp in the example should be created, see the definition
of the columns for xp_logininfo in Books Online.

--
Erland Sommarskog, SQL Server MVP, esquel@.sommarskog.se

Books Online for SQL Server SP3 at
http://www.microsoft.com/sql/techin.../2000/books.asp

join table with procedure?

Is it possible to join the results of a stored procedure with a table?
SELECT field1, field2, field3 FROM tblCustomer INNER JOIN (exec spTest
'inputvar' AS SP) ON tblCustomer.CustID = SP.CustID
Thanks,
KeithKeith G Hicks,
You need to grab the result of the sp into a table (permanent or temporal)
and use the table in the join, or you can re-write the sp as a table functio
n.
create table #t1(c1 ...)
insert into #t1(c1, ...)
exec spTest 'inputvar'
SELECT field1, field2, field3
FROM tblCustomer INNER JOIN #t1 AS SP ON tblCustomer.CustID = SP.CustID
drop table #t1
go
How to share data between stored procedures
http://www.sommarskog.se/share_data.html
AMB
"Keith G Hicks" wrote:

> Is it possible to join the results of a stored procedure with a table?
> SELECT field1, field2, field3 FROM tblCustomer INNER JOIN (exec spTest
> 'inputvar' AS SP) ON tblCustomer.CustID = SP.CustID
> Thanks,
> Keith
>
>|||Cool. That's what I'm doing. I just wasn't sure if there was a way to join
directly to the procedure. Thanks for the info.
"Alejandro Mesa" <AlejandroMesa@.discussions.microsoft.com> wrote in message
news:8D7D36E8-8EF7-4E4B-8613-59F8BC64148C@.microsoft.com...
Keith G Hicks,
You need to grab the result of the sp into a table (permanent or temporal)
and use the table in the join, or you can re-write the sp as a table
function.
create table #t1(c1 ...)
insert into #t1(c1, ...)
exec spTest 'inputvar'
SELECT field1, field2, field3
FROM tblCustomer INNER JOIN #t1 AS SP ON tblCustomer.CustID = SP.CustID
drop table #t1
go
How to share data between stored procedures
http://www.sommarskog.se/share_data.html
AMB
"Keith G Hicks" wrote:

> Is it possible to join the results of a stored procedure with a table?
> SELECT field1, field2, field3 FROM tblCustomer INNER JOIN (exec spTest
> 'inputvar' AS SP) ON tblCustomer.CustID = SP.CustID
> Thanks,
> Keith
>
>

Join stored procedures?

Hi all,

I have a challenge (not a problem). Simplifing it as far as i could, i
have this situation:

Table Persons
Id (PK)
Name

Table Scores
FK_Person (PK)
Period (PK)
Value

Now, i want to make a stored procedure that returns the scores for all
people in a certain period. So i have:

CREATE PROCEDURE [dbo].[ScorePerson]
(@.Period Int)
AS
SELECT dbo.People.Name, dbo.Scores.[Value]
FROM dbo.People LEFT OUTER JOIN
dbo.Scores ON dbo.People.Id =
dbo.Scores.FK_person
WHERE dbo.Scores.Period = @.Period
GO

BUT: if a person has no score for a certain period, he will not show
up in the result set at all, but i do want him to. So what i need to
do is first get the subset for a period from the table Scores and THEN
Left join that to the persons, so i always get all persons and only a
value for the the score if there is one.

How can i do this? I could store the results in a temporary table but
that just feels 'unpure', wrong. Is there any way i can get this in a
single pass? Can i for example join two stored procedures with
parameters together in another SP that passes these params on to them?

TIA,

Gert-JanIf you have no Periods table, you can get the list of periods based on your
Scores table. Of course, this technique will only return periods with at
least one row in the Scores table so you'll need a Periods table if you need
to include periods with no scores. Below is an example:

SELECT
dbo.People.Name,
dbo.Scores.[Value]
FROM dbo.People
LEFT JOIN dbo.Scores ON
dbo.People.Id = dbo.Scores.FK_person AND
dbo.Scores.Period = @.Period
CROSS JOIN
(SELECT DISTINCT Period
FROM Scores) AS Periods
WHERE Periods.Period = @.Period

--
Hope this helps.

Dan Guzman
SQL Server MVP

"G.J. v.d. Kamp" <gjvdkamp@.hotmail.com> wrote in message
news:d49d68a1.0411250718.59c0b023@.posting.google.c om...
> Hi all,
> I have a challenge (not a problem). Simplifing it as far as i could, i
> have this situation:
> Table Persons
> Id (PK)
> Name
> Table Scores
> FK_Person (PK)
> Period (PK)
> Value
> Now, i want to make a stored procedure that returns the scores for all
> people in a certain period. So i have:
> CREATE PROCEDURE [dbo].[ScorePerson]
> (@.Period Int)
> AS
> SELECT dbo.People.Name, dbo.Scores.[Value]
> FROM dbo.People LEFT OUTER JOIN
> dbo.Scores ON dbo.People.Id =
> dbo.Scores.FK_person
> WHERE dbo.Scores.Period = @.Period
> GO
> BUT: if a person has no score for a certain period, he will not show
> up in the result set at all, but i do want him to. So what i need to
> do is first get the subset for a period from the table Scores and THEN
> Left join that to the persons, so i always get all persons and only a
> value for the the score if there is one.
> How can i do this? I could store the results in a temporary table but
> that just feels 'unpure', wrong. Is there any way i can get this in a
> single pass? Can i for example join two stored procedures with
> parameters together in another SP that passes these params on to them?
> TIA,
> Gert-Jan|||Please post DDL, so that people do not have to guess what the keys,
constraints, Declarative Referential Integrity, datatypes, etc. in
your schema are. Sample data is also a good idea, along with clear
specifications.

You also need to read a basic book on data modeling and the ISO-11179
naming conventions. How many different names did you post for the same
data element? Why are tables that share a data element modeled as if
they had no DRI relationships in your personal pseudo-code?

CREATE TABLE Persons
(player_id INTEGER NOT NULL PRIMARY KEY,
name CHAR(35) NOT NULL);

CREATE TABLE Games
(player_id INTEGER NOT NULL
REFERENCES Persons (player_id),
period_nbr INTEGER NOT NULL,
score INTEGER NOT NULL CHECK (score >= 0));

>> I want to make a stored procedure that returns the scores for all
people in a certain period. <<

Why do you still think in procedural terms in a non-procedural
language? Why not a VIEW?

CREATE VIEW TotalScores (player_name, period_nbr, score_tot)
AS
SELECT P.player_name, G.period_nbr, SUM(G.score_tot)
FROM Persons AS P
LEFT OUTER JOIN
Games AS G
ON P.player_id = G.player_id
GROUP BY player_id, period_nbr;

Then you can use this query

SELECT player_name, @.my_period_nbr, score_tot
FROM TotalScores
WHERE @.my_period_nbr = period_nbr;

A zero means he played and did not score; a NULL means he did not play
at all.|||On 25 Nov 2004 10:39:49 -0800, --CELKO-- wrote:

(snip)
>CREATE VIEW TotalScores (player_name, period_nbr, score_tot)
>AS
>SELECT P.player_name, G.period_nbr, SUM(G.score_tot)
> FROM Persons AS P
> LEFT OUTER JOIN
> Games AS G
> ON P.player_id = G.player_id
> GROUP BY player_id, period_nbr;

Hi Joe,

Maybe you should have tested this before posting!

Server: Msg 170, Level 15, State 1, Procedure TotalScores, Line 8
Line 8: Incorrect syntax near ';'.

(Okay, this is buggy behaviour of SQL Server - but this IS a SQL Server
group, after all!)

Remove the semicolon; retry:

Server: Msg 207, Level 16, State 3, Procedure TotalScores, Line 3
Invalid column name 'player_name'.
Server: Msg 207, Level 16, State 1, Procedure TotalScores, Line 3
Invalid column name 'score_tot'.
Server: Msg 209, Level 16, State 1, Procedure TotalScores, Line 3
Ambiguous column name 'player_id'.

Change player_name to name and score_tot to score in the SELECT and add P.
in front of player_id in the GROUP BY; retry:

Server: Msg 8120, Level 16, State 1, Procedure TotalScores, Line 3
Column 'P.name' is invalid in the select list because it is not contained
in either an aggregate function or the GROUP BY clause.

Okay, add P.name to the group by (or enclose it in an aggregate function),
retry and finally the view is made (whew!).

>Then you can use this query
>SELECT player_name, @.my_period_nbr, score_tot
> FROM TotalScores
> WHERE @.my_period_nbr = period_nbr;
>A zero means he played and did not score; a NULL means he did not play
>at all.

Let's enter some data to test it. Two persons (Joe and Hugo). Both have a
score in period 1, Joe has a score in period 2 and Hugo in period 3.

insert Persons values(1,'Joe')
insert Persons values(2,'Hugo')
insert Games values (1, 1, 1)
insert Games values (2, 1, 2)
insert Games values (1, 2, 3)
insert Games values (2, 3, 0)
GO
declare @.my_period_nbr int
set @.my_period_nbr = 1
SELECT player_name, @.my_period_nbr, score_tot
FROM TotalScores
WHERE @.my_period_nbr = period_nbr;
set @.my_period_nbr = 2
SELECT player_name, @.my_period_nbr, score_tot
FROM TotalScores
WHERE @.my_period_nbr = period_nbr;
set @.my_period_nbr = 3
SELECT player_name, @.my_period_nbr, score_tot
FROM TotalScores
WHERE @.my_period_nbr = period_nbr;

Does this return the data that the poster asked for? Does this return Hugo
in period 2 and Joe in period 3, even though they have no score in that
period?

Unfortunately - no.

Best, Hugo
--

(Remove _NO_ and _SPAM_ to get my e-mail address)|||On 25 Nov 2004 07:18:55 -0800, G.J. v.d. Kamp wrote:

(snip)
>BUT: if a person has no score for a certain period, he will not show
>up in the result set at all, but i do want him to. So what i need to
>do is first get the subset for a period from the table Scores and THEN
>Left join that to the persons, so i always get all persons and only a
>value for the the score if there is one.

Hi Gert-Jan,

This is actually lots simpler than you think!

SELECT dbo.People.Name, dbo.Scores.[Value]
FROM dbo.People LEFT OUTER JOIN
dbo.Scores ON dbo.People.Id =
dbo.Scores.FK_person
AND dbo.Scores.Period = @.Period

(The only change is to move the filter condition for period to the join
condition!!)

Best, Hugo
--

(Remove _NO_ and _SPAM_ to get my e-mail address)|||Hi all,

Thanks everyone for your time.

Dan, works like a charm, thanks! It obviously does help to have a
thorough foundation in math.

Celko, i only described the problem in a generic way, i thought it
would be a common problem a person more experienced than me would
recognize. (and they did). Also, a view doesn't take parameters as far
as i know. THe point about SQL not being a procedural language is
usually a good one, personally i don't think very highly of people who
break out cursors for the simplest of inserts. But i don't think it's
just in this case. Thanks anyway.

But of course first prize goes to Hugo for the lean of going about it.
I like lean, and now i like Hugo (In a friendly way, don't worry!)
Thanks!

Regards GJ

Hugo Kornelis <hugo@.pe_NO_rFact.in_SPAM_fo> wrote in message news:<h5qcq09cmd963c7vutuq1v2ru9gqdd7rld@.4ax.com>...
> On 25 Nov 2004 07:18:55 -0800, G.J. v.d. Kamp wrote:
> (snip)
> >BUT: if a person has no score for a certain period, he will not show
> >up in the result set at all, but i do want him to. So what i need to
> >do is first get the subset for a period from the table Scores and THEN
> >Left join that to the persons, so i always get all persons and only a
> >value for the the score if there is one.
> Hi Gert-Jan,
> This is actually lots simpler than you think!
> SELECT dbo.People.Name, dbo.Scores.[Value]
> FROM dbo.People LEFT OUTER JOIN
> dbo.Scores ON dbo.People.Id =
> dbo.Scores.FK_person
> AND dbo.Scores.Period = @.Period
> (The only change is to move the filter condition for period to the join
> condition!!)
> Best, Hugo|||Celko,

Your solution will probably work as well, but i just like to keap my
asp code as neat as possible, so i move all the logic to the
SQL-server as much as i can. Also, in my real world problem, it would
theoretically be possible to have a zero score as a value.

But thanks anyway.

Regards GJ

jcelko212@.earthlink.net (--CELKO--) wrote in message news:<18c7b3c2.0411251039.116b316d@.posting.google.com>...
> Please post DDL, so that people do not have to guess what the keys,
> constraints, Declarative Referential Integrity, datatypes, etc. in
> your schema are. Sample data is also a good idea, along with clear
> specifications.
> You also need to read a basic book on data modeling and the ISO-11179
> naming conventions. How many different names did you post for the same
> data element? Why are tables that share a data element modeled as if
> they had no DRI relationships in your personal pseudo-code?
> CREATE TABLE Persons
> (player_id INTEGER NOT NULL PRIMARY KEY,
> name CHAR(35) NOT NULL);
> CREATE TABLE Games
> (player_id INTEGER NOT NULL
> REFERENCES Persons (player_id),
> period_nbr INTEGER NOT NULL,
> score INTEGER NOT NULL CHECK (score >= 0));
> >> I want to make a stored procedure that returns the scores for all
> people in a certain period. <<
> Why do you still think in procedural terms in a non-procedural
> language? Why not a VIEW?
> CREATE VIEW TotalScores (player_name, period_nbr, score_tot)
> AS
> SELECT P.player_name, G.period_nbr, SUM(G.score_tot)
> FROM Persons AS P
> LEFT OUTER JOIN
> Games AS G
> ON P.player_id = G.player_id
> GROUP BY player_id, period_nbr;
> Then you can use this query
> SELECT player_name, @.my_period_nbr, score_tot
> FROM TotalScores
> WHERE @.my_period_nbr = period_nbr;
> A zero means he played and did not score; a NULL means he did not play
> at all.|||"G.J. v.d. Kamp" <gjvdkamp@.hotmail.com> wrote in message news:d49d68a1.0411260025.681e9a65@.posting.google.c om...
> Also, a view doesn't take parameters as far
> as i know.

Views don't take parameters in the same way as procedures and functions, but you can still use your parameters...

Select *
from myView
where myView.col1 = @.myParameter ;

The view is created without the parameter @.myParameter, but it's easy to write queries on the view that use them.

--
Paul Horan
Sr. Architect
VCI Springfield, Mass
www.vcisolutions.com

join stored procedure and view

Hi everybody
I have this stored procedure called flydate
CREATE PROCEDURE FlyDate AS
declare @.gencalendar table (cal_date datetime primary key)
declare @.p_date datetime
set @.p_date =getdate()

while @.p_date > DateAdd(mm, -3, GetDate()) BEGIN
insert into @.gencalendar(cal_date)
VALUES(@.p_date)

--getdate
SET @.p_date = DateAdd(d, -1, @.p_date)
END

select cal_date AS KF_DATE,0 AS KF_STATUS from @.gencalendar
GO

-which returns all the date for the past three month
and this is my view
CREATE VIEW dbo.rpt_Kids
AS
SELECT TOP 100 PERCENT
KF_ID,dbo.just_date_formal(KF_DATE) as KF_DATE,KF_STATUS FROM dbo.KIDS
order by Year(KF_date) DESC,Month(KF_date) DESC,Day(KF_date) DESC

just_date_formal function
CREATE FUNCTION [dbo].[just_date_formal](@.dtvalue datetime)
RETURNS nvarchar(40)
AS
BEGIN
DECLARE @.display nvarchar(40)
SET @.display = CAST(DATEPART(dd, @.dtvalue) AS nvarchar) + ' ' + CAST(DATEPART(mm, @.dtvalue) AS nvarchar) + ' ' + CAST(DATEPART(yyyy, @.dtvalue) AS nvarchar) + ', ' + CAST(DATENAME(dw, @.dtvalue) AS nvarchar)
RETURN @.display
END

this returns all the date on which error is generated.on other dates on which no error message is generated.
now i want to join both of them so that i get dates of error message and those dates also on which error message is not generated
like

23 june 2005 error
22 june 2005
21 june 2005 error

it should return all dates regardless errror is there or not

Hi,

You directly cannot JOIN the output of a stored procedure in a FROM clause. Stored procedures cannot be used in contexts that require relational expressions. I realize this seems odd at first, since you *can* return a rowset from a stored procedure. However, the reasons we disallow it in TSQL are

(a) The shape of the rowset cannot be determined ahead of time (there is no metadata anywhere that describes the table returned by a stored proc, and besides, the shape returned might depend on the run-time execution path though the proc ... if (condition) select * from somewhere else select * from somewherelese)

and (b) a stored procedure can return > 1 result set.

You have a few options available

1) You can capture the output of the stored procedure into a temporary table using the INSERT INTO EXEC syntax. The code would looks something like:

create table #tempcal(KF_DATE datetime, KF_STATUS int)
go

insert into #tempcal exec FlyDate
go

now you can JOIN on #tempcal.

2) You can refactor your proc to make it into a table-valued function, which you *can* use in a JOIN. You will have to factor-out the non-deterministic getdata() and pass them in as parameters. The code would look something like this

create function FlyDateFunc(@.p_date datetime, @.p_today datetime)
returns @.gencalendar table (KF_DATE datetime primary key, KF_STATUS int)
as
begin
while @.p_date > DateAdd(mm, -3, @.p_today)
begin
insert into @.gencalendar values (@.p_date, 0)
set @.p_date = DateAdd(d, -1, @.p_date)
end

return
end
go

select * from FlyDateFunc(getdate() , getdate())
go

Does this answer your question?
Thanks

|||

Hi,

I have an extra complication to this problem. I have SP's that create dynamic columns based on the parameters they get. So i don't know in advance what my #table should look like. Is there any way to do this without knowing the columns of the #table? (like the select * into #tmp from table1 but then using EXEC? )

I have developed SP's that create dyn columns. Now i want to use these same SP's in SSRS, but that want's to know the column names in advance. So i want to store the results of the SP in a #table and then unpivot that to send it to RS. Think that'll work?

[edit] the SP's use dynamic SQL to get the results

Regards Gert-Jan

join stored procedure and view

Hi everybody
I have this stored procedure called flydate
CREATE PROCEDURE FlyDate AS
declare @.gencalendar table (cal_date datetime primary key)
declare @.p_date datetime
set @.p_date =getdate()

while @.p_date > DateAdd(mm, -3, GetDate()) BEGIN
insert into @.gencalendar(cal_date)
VALUES(@.p_date)

--getdate
SET @.p_date = DateAdd(d, -1, @.p_date)
END

select cal_date AS KF_DATE,0 AS KF_STATUS from @.gencalendar
GO

-which returns all the date for the past three month
and this is my view
CREATE VIEW dbo.rpt_Kids
AS
SELECT TOP 100 PERCENT
KF_ID,dbo.just_date_formal(KF_DATE) as KF_DATE,KF_STATUS FROM dbo.KIDS
order by Year(KF_date) DESC,Month(KF_date) DESC,Day(KF_date) DESC

just_date_formal function
CREATE FUNCTION [dbo].[just_date_formal](@.dtvalue datetime)
RETURNS nvarchar(40)
AS
BEGIN
DECLARE @.display nvarchar(40)
SET @.display = CAST(DATEPART(dd, @.dtvalue) AS nvarchar) + ' ' + CAST(DATEPART(mm, @.dtvalue) AS nvarchar) + ' ' + CAST(DATEPART(yyyy, @.dtvalue) AS nvarchar) + ', ' + CAST(DATENAME(dw, @.dtvalue) AS nvarchar)
RETURN @.display
END

this returns all the date on which error is generated.on other dates on which no error message is generated.
now i want to join both of them so that i get dates of error message and those dates also on which error message is not generated
like

23 june 2005 error
22 june 2005
21 june 2005 error

it should return all dates regardless errror is there or not

Hi,

You directly cannot JOIN the output of a stored procedure in a FROM clause. Stored procedures cannot be used in contexts that require relational expressions. I realize this seems odd at first, since you *can* return a rowset from a stored procedure. However, the reasons we disallow it in TSQL are

(a) The shape of the rowset cannot be determined ahead of time (there is no metadata anywhere that describes the table returned by a stored proc, and besides, the shape returned might depend on the run-time execution path though the proc ... if (condition) select * from somewhere else select * from somewherelese)

and (b) a stored procedure can return > 1 result set.

You have a few options available

1) You can capture the output of the stored procedure into a temporary table using the INSERT INTO EXEC syntax. The code would looks something like:

create table #tempcal(KF_DATE datetime, KF_STATUS int)
go

insert into #tempcal exec FlyDate
go

now you can JOIN on #tempcal.

2) You can refactor your proc to make it into a table-valued function, which you *can* use in a JOIN. You will have to factor-out the non-deterministic getdata() and pass them in as parameters. The code would look something like this

create function FlyDateFunc(@.p_date datetime, @.p_today datetime)
returns @.gencalendar table (KF_DATE datetime primary key, KF_STATUS int)
as
begin

while @.p_date > DateAdd(mm, -3, @.p_today)
begin
insert into @.gencalendar values (@.p_date, 0)
set @.p_date = DateAdd(d, -1, @.p_date)
end

return
end
go

select * from FlyDateFunc(getdate() , getdate())
go

Does this answer your question?
Thanks

|||

Hi,

I have an extra complication to this problem. I have SP's that create dynamic columns based on the parameters they get. So i don't know in advance what my #table should look like. Is there any way to do this without knowing the columns of the #table? (like the select * into #tmp from table1 but then using EXEC? )

I have developed SP's that create dyn columns. Now i want to use these same SP's in SSRS, but that want's to know the column names in advance. So i want to store the results of the SP in a #table and then unpivot that to send it to RS. Think that'll work?

[edit] the SP's use dynamic SQL to get the results

Regards Gert-Jan