sql server 2000 and for xml explicit - sql-server-2000

I've got a problem with using for xml explicit in SQL Server 2000 (so I can't use the new path() stuff from sql 2005/8)
Essentially I have two tables and the XML structure I want to have is
<xml>
<table_1 field1="foo" field2="foobar2" field3="foobar3">
<a_row_from_table_2 field1="goo" field2="goobar2" field3="goobar3" />
<a_row_from_table_2 field1="hoo" field2="hoobar2" field3="hoobar3" />
</table_1>
</xml>
That is, table_1 has a one-to-many relationship with table_2, and I want to make a hierarchy of it.
So far I can't seem to get it, the closest I've managed to get is all the records from table1, with all the records from table2 appended to the very last element of table1
Any help with setting up this kind of relationship would be greatly appreciated.
-Marcin

Does your query include an order by clause? In for xml explicit mode, it's important that information appears in the sequence it's needed. For example, in the Northwind example database, you can generate a nested XML for employee territories like:
select
1 as Tag,
Null as Parent,
e.EmployeeId as [Employee!1!EmployeeId],
e.LastName as [Employee!1!LastName],
Null as [EmployeeTerritories!2!TerritoryID]
from dbo.Employees e
union all
select 2 as Tag,
1 as Parent,
et.EmployeeId as [Employee!1!EmployeeId],
Null as [Employee!1!LastName],
et.TerritoryId as [EmployeeTerritories!2!TerritoryID]
from dbo.EmployeeTerritories et
order by [Employee!1!EmployeeId], Parent
for xml explicit
This results in an XML like:
<Employee EmployeeId="1" LastName="Davolio">
<EmployeeTerritories TerritoryID="06897" />
<EmployeeTerritories TerritoryID="19713" />
</Employee>
<Employee EmployeeId="2" LastName="Fuller">
...
To get an idea of how it works, run the query without the for xml explicit.

Related

Spooky query behavior : Same query, different results when inside a view

The same query brings different results when inside a View.
I tried to force same codepages, same data types, Common Query Expressions... none worked.
Have a look at this simple query:
SELECT TOP 100 CompanyID, SubsidiaryID
FROM STAGING.SALESAX S
INNER JOIN Subsidiary SU
ON S.CompanyID = SU.SubsidiaryAXCode
It returns all expected 100 rows.
If I use the EXACT SAME QUERY in a view:
CREATE VIEW [STAGING].[VSalesAXBASE]
AS
SELECT TOP 100 CompanyID, SubsidiaryID
FROM STAGING.SALESAX S
INNER JOIN Subsidiary SU
ON S.CompanyID = SU.SubsidiaryAXCode
GO
SELECT * FROM [STAGING].[VSalesAXBASE]
it returns 0 ROWS
You prefix SALESAX table with STAGING., but don't prefix Subsidiary table in the query. Do prefix all tables in the query.
One possibility is that there are several Subsidiary tables and the query uses different table in the context of the view.
By the way, it is also a good practice to prefix columns with table names in the SELECT part of the query. For example, right now it is hard to know from which table(s) the columns CompanyID and SubsidiaryID come from.
The solution was to add the DBO schemma to the subsidiary table.. thanks to the suggestions of #VladimirBaranov, #IMSoP and #Augustina(Codec)
Looks like the execution context of the view may be different from the current user (need to check more on this).
SQL does not guarantee the ordering of results unless an explicit Order By clause is used.

How To Find Related Record ID Based Reference Document No on SQL Statement

I need to show related record id based document no as reference in same table. I try many time and direction but cannot get a right output.
This below are table and data:
Table A
Basically Record ID no 2,4 and 10 are related based on Reference Document No. For example if I select record id no 4 I still can list all related document from first to last transaction.
I hope someone who cross this problem or anybody have a solution from SQL Statement or coding on .net please as long I can show this result.
I assume you're using postgres, since this is tagged with it. You can make a recursive query that will accomplish what you want when you're querying for a given docno:
WITH RECURSIVE t AS (
SELECT docno, refdocno
FROM <table>
WHERE docno = 'T0003'
UNION
SELECT blah.docno, blah.refdocno
FROM <table>
JOIN t ON t.docno = blah.refdocno
OR t.refdocno = blah.docno
)
SELECT *
FROM t;
Note: you'll have to put the docno you're searching for in the with statement. If you need other columns, you can put them in there as well.
PS. I assume that row 10's refdocno was supposed to be T0003 in your example
Are you wanting to link all documents on the parent document? If you wanted to, say get a document and find all related documents for docno XY001 (assuming XY001 is the parent Document otherwise link the other way around)
You could use
SELECT *
FROM TableA AS parentDoc
LEFT OUTER JOIN TableA AS referentialDoc ON parentDoc.docno = referentialDoc.refdocno
WHERE parentDoc.docno = XY001
Of Course you can change the WHERE clause to
WHERE referentialDoc.docno IS NOT NULL
to show only those with a referential document.
also note that this is only good for a structure of parent - child. for structure of grandparent-parent-child and more, you will need to either expand the Query or do it programmatically.
After try Ramfjord solution I got a result what I want. I just add a little touch to sequence my result where I can see from first until last transactions like below:
WITH RECURSIVE t AS (
SELECT **recid**, docno, refdocno
FROM <table>
WHERE docno = 'T0003'
UNION
SELECT **c.recid**, docno, refdocno
FROM <table> c
JOIN t ON t.docno = c.refdocno
OR t.refdocno = c.docno
)
SELECT *
FROM t **order by recid**;
Ramfjord you already save my day!
Spasticmonkey your solutions also good for Parent-Child table. I will use your solution for other task.

Reusing results from a SQL query in a following query in Sqlite

I am using a recursive with statement to select all child from a given parent in a table representing tree structured entries. This is in Sqlite (which now supports recursive with).
This allows me to select very quickly thousands of record in this tree whithout suffering the huge performance loss due to preparing thousands of select statements from the calling application.
WITH RECURSIVE q(Id) AS
(
SELECT Id FROM Entity
WHERE Parent=(?)
UNION ALL
SELECT m.Id FROM Entity AS m
JOIN Entity ON m.Id=q.Parent
)
SELECT Id FROM q;
Now, suppose I have related data to these entities in an arbitrary number of other tables, that I want to subsequently load. Due to the arbitrary number of them (in a modular fashion) it is not possible to include the data fetching directly in this one. They must follow it.
But, if for each related tables I then do a SELECT statement, all the performance gain from selecting all the data from the tree directly inside Sqlite is almost useless because I will still stall on thousands of subsequent requests which will each prepare and issue a select statement.
So two questions :
The better solution is to formulate a similar recursive statement for each of the related tables, that will recursively gather the entities from this tree again, and this time select their related data by joining it.
This sounds really more efficient, but it's really tricky to formulate such a statement and I'm a bit lost here.
Now the real mystery is, would there be an even more efficient solution, which would be to somehow keep these results from the last query cached somewhere (the rows with the ids from the entity tree) and join them to the related tables in the following statement without having to recursively iterate over it again ?
Here is a try at the first option, supposing I want to select a field Data from related table Component : is the second UNION ALL legal ?
WITH RECURSIVE q(Data) AS
(
SELECT Id FROM Entity
WHERE Parent=(?)
UNION ALL
SELECT m.Id FROM Entity AS m
JOIN Entity ON m.Id=q.Parent
UNION ALL
SELECT Data FROM Component AS c
JOIN Component ON c.Id=q.Id
)
SELECT Data FROM q;
The documentation says:
 2. The table named on the left-hand side of the AS keyword must appear exactly once in the FROM clause of the right-most SELECT statement of the compound select, and nowhere else.
So your second query is not legal.
However, the CTE behaves like a normal table/view, so you can just join it to the related table:
WITH RECURSIVE q(Id) AS
( ... )
SELECT q.Id, c.Data
FROM q JOIN Component AS c ON q.Id = c.Id
If you want to reuse the computed values in q for multiple queries, there's nothing you can do with CTEs, but you can store them in a temporary table:
CREATE TEMPORARY TABLE q_123 AS
WITH RECURSIVE q(Id) AS
( ... )
SELECT Id FROM q;
SELECT * FROM q_123 JOIN Component ...;
SELECT * FROM q_123 JOIN Whatever ...;
DROP TABLE q_123;

In continue of questions "DB Schema for storing tagged records" -- how to select list of items with tags?

Good day!
There are a lot of questions how to store tags in DB here on stackoverflow, I finally decide to use Toxi approach (items table, tags table and many-to-many intermediate table) http://www.pui.ch/phred/archives/2005/04/tags-database-schemas.html
I want to display a list of 20-50 tagged items on a page each with list of it's tags (I use LINQ2SQL in ASP.NET 3.5).
I see some options:
First query for list of items than run query for each item to select tags for each item -- seems to be slow, but caching on application level can improve situation.
Denormalize items table and store list of tags for item in text field in "items" table.
However both options seem bad to me, may be I'm missing something?
Thanks in advance!
I don't recommend Option #2 because it will overcomplicate attempts to isolate a tag or group of tags. My recommendation would be to leave the data model as is (ITEMS, TAGS, ITEM_TAGS_XREF), and query against a VIEW which would contain a computed column containing the list of tags. If you mentioned what database you're using, we can provide the query that will construct a comma/etc delimited string of the tags an item is associated with.
Assuming primary and foreign keys are setup accordingly, the performance shouldn't be bad - is it possible the lag is occurring in the application layer?
If I understood correctly ...
Maybe you could create a query that joins all three table. In only one fast query, you would get all information... In SQL, it could be something like:
select ... //itemColumns, tagColumns
from item
join tagItem on item.id = tagItem.itemId
join tag on tag.id = tagItem.tagId
where ... // your other conditions
2KLE: thanks, I got it. The result of this query is one row for each tags (Item data is duplicated), so anyway there is need to process resultset in application code. Am I right?
For LINQ 2 SQL I used DataLoadOptions to specify what associated data I want to load. Here is an example of code generated by LINQ2SQL to select all items with all tags.
Please note that Items table is called Snippets in my example (so we have Snippets, Tags and SnippetsTags tables). Another thing to note is that LINQ2SQL doesn't support Many-To-Many relations out of the box, so there is an entity class for intermediate table (SnippetsTag). Here are C# code:
using (SnippetsDataContext context = UtilsLinq.CreateContext())
{
DataLoadOptions dl = new DataLoadOptions();
dl.LoadWith<Snippet>(s => s.SnippetsTags);
dl.LoadWith<SnippetsTag>(st => st.Tag);
context.LoadOptions = dl;
var result = (from s in context.Snippets
select s).ToList();
string x = result.First().SnippetsTags.First().Tag.Title;
}
Here is a SQL which LINQ to SQL generates:
SELECT [t0].[Id], [t0].[Title], [t0].[Text], [t0].[Created], [t1].[Id] AS [Id2], [t1].[TagId], [t1].[SnippetId], [t2].[Id] AS [Id3], [t2].[Title] AS [Title2], (
SELECT COUNT(*)
FROM [dbo].[SnippetsTags] AS [t3]
INNER JOIN [dbo].[Tags] AS [t4] ON [t4].[Id] = [t3].[TagId]
WHERE [t3].[SnippetId] = [t0].[Id]
) AS [value]
FROM [dbo].[Snippets] AS [t0]
LEFT OUTER JOIN ([dbo].[SnippetsTags] AS [t1]
INNER JOIN [dbo].[Tags] AS [t2] ON [t2].[Id] = [t1].[TagId]) ON [t1].[SnippetId] = [t0].[Id]
ORDER BY [t0].[Id], [t1].[Id], [t2].[Id]

Which tags are not in the database?

Given a collection of user specified tags how do I determine which ones are not in the tags table with 1 SQL Statement?
Assuming a table schema tags (id, tag) and I'm using mysql, if there's an optimization I'm unaware of.
thanks
SELECT Tag
FROM UserSpecifiedTags
LEFT OUTER JOIN AllTags ON UserSpecifiedTags.Tag = AllTags.Tag
WHERE AllTags.Tag IS NULL
This should return what you want. In my experience, executing a join and looking for rows which don't have a match is much quicker than using the IN operator.
select * from canonical_list_of_tags where tag not in (select tag from used_tags)
At least that works in T-SQL for SQL Server ...
Edit: Assuming that the table canonical_list_of_tags is populated with the result of "Given a collection of user specified tags"
select
utt.tagName
from
userTypedTags utt
left join tag t on utt.tagName = t.tag
where
t.ID is null
and utt.userID = <ID of the User in question>
That is assuming that you have table
userTypedTags(userID, tagName)
I have added a related question