SQL server XML Parsing to Table - sql

I am new to SQL xml operations. I have a problem with SQL & XML Parsing.
I have a Table named Task. It has 3 columns:
Name
Task
Date
Task is saving in Hours worked as an xml in the following format:
<TASK>
<A>1</A>
<B>4</B>
<C>0</C>
</TASK>
My table will look like this (with multiple employees)
Name | Task | Date
========================================================================
Employee2219 | <TASK><A>1</A><B>4</B><C>0</C></ TASK > | 2014-01-28
Employee2219 | <TASK><A>3</A><B>2</B><C>1</C></ TASK > | 2014-01-29
....
I need to calculate the hours spend per employee for each task in a week like:
Name | A | B | C | D
===============================
Employee2219 | 4 | 6 | 1 | 0
....
I am new to XML and I could not work this out.

It is straightforward to extract the xml using XQuery:
SELECT
Name,
SUM(TaskA) AS ATotal,
SUM(TaskB) AS BTotal,
SUM(TaskC) AS CTotal,
SUM(TaskD) AS DTotal
FROM
(
SELECT
t.NAME,
t.Date,
Nodes.node.value('(A)[1]', 'int') AS TaskA,
Nodes.node.value('(B)[1]', 'int') AS TaskB,
Nodes.node.value('(C)[1]', 'int') AS TaskC,
Nodes.node.value('(D)[1]', 'int') AS TaskD
FROM
TASK t
cross apply t.Task.nodes('/TASK') as Nodes(node)
) x
WHERE
[Date] BETWEEN '2014-01-01' AND '2014-01-07' -- Your week range
GROUP BY
Name;
SqlFiddle here
Please post your question in text - many corporate SO users are blocked from sites like imgur, so answering becomes guess work.

Related

Writing a String comparison function in bigquery

I am trying to write a function with bigquery UDF to compare a list of string with other list of strings.
basically I would like to know how many new users do we have per week and from these new Users how many of them kept visiting our website in future weeks. For that I created a query which gives me a String of all emails per week (with group_concat) and saved it as a table. now need to know how can I compare each with Other collections of emails per week.
At the end, I would like to have a table like this :
+----------------+-------+-------+--------+------+
| | week 1 | week 2 | week 3| week 4 | ... |
+----------------+-------+-------+--------+------+
| week1 | 17 | 7 | 5 | 9 | ... |
+----------------+-------+-------+--------+------+
| week2 | | 19 | 13 | 8 | ... |
+-----------------+-------+-------+--------+-----+
| week3 | | | 24 | 15 | ... |
+-----------------+-------+-------+--------+-----+
Just to give you an idea to play with
SELECT
CONCAT('week', STRING(prev)) AS WEEK,
SUM(IF(next=19, authors, 0)) AS week19,
SUM(IF(next=20, authors, 0)) AS week20,
SUM(IF(next=21, authors, 0)) AS week21,
SUM(IF(next=22, authors, 0)) AS week22,
SUM(IF(next=23, authors, 0)) AS week23
FROM (
SELECT prev, next, COUNT(author) AS authors
FROM (
SELECT
prev_week.week_created AS prev,
next_week.week_created AS next,
prev_week.author AS author
FROM (
SELECT
WEEK(SEC_TO_TIMESTAMP(created_utc)) AS week_created,
author
FROM [fh-bigquery:reddit_posts.2016_05]
GROUP BY 1,2
) next_week
LEFT JOIN (
SELECT
WEEK(SEC_TO_TIMESTAMP(created_utc)) AS week_created,
author
FROM [fh-bigquery:reddit_posts.2016_05]
GROUP BY 1,2
) AS prev_week
ON prev_week.author = next_week.author
HAVING prev <= next
)
GROUP BY 1,2
)
GROUP BY 1
ORDER BY 1
Result is as below
This is the closest to what you asked i can think of
Meantime, please note - BigQuery is less tailored for reports design rather for data crunching. So I think that creating matrix/pivot within BigQuery (outer select) is not the best fit - it can be done in your reporting tool. But calculating all pairs prev|next|count (inner select) is definitely suitable here in BigQuery

Count and name content from a SQL Server table

I have a table which is structured like this:
+-----+-------------+-------------------------+
| id | name | timestamp |
+-----+-------------+-------------------------+
| 1 | someName | 2016-04-20 09:41:41.213 |
| 2 | someName | 2016-04-20 09:42:41.213 |
| 3 | anotherName | 2016-04-20 09:43:41.213 |
| ... | ... | ... |
+-----+-------------+-------------------------+
Now, I am trying to create a query, which selects all timestamps since time x and count the amount of times the same name occurs in the result.
As an example, if we would apply this query to the table above, with 2016-04-20 09:40:41.213 as the date from which on it should be counted, the result should look like this:
+-------------+-------+
| name | count |
+-------------+-------+
| someName | 2 |
| anotherName | 1 |
+-------------+-------+
What I have accomplished so far is the following query, which gives me the the names, but not their count:
WITH screenshots AS
(
SELECT * FROM SavedScreenshotsLog
WHERE timestamp > '2016-04-20 09:40:241.213'
)
SELECT s.name
FROM SavedScreenshotsLog s
INNER JOIN screenshots sc ON sc.name = s.name AND sc.timestamp = s.timestamp
ORDER BY s.name
I have browsed through stackoverflow but was not able to find a solution which fits my needs and as I am not very experienced with SQL, I am out of ideas.
You mention one table in your question, and then show a query with two tables. That makes it hard to follow the question.
What you are asking for is a simple aggregation:
SELECT name, COUNT(*)
FROM SavedScreenshotsLog
WHERE timestamp > '2016-04-20 09:40:241.213'
GROUP BY name
ORDER BY COUNT(*) DESC;
EDIT:
If you want "0" values, you can use conditional aggregation:
SELECT name,
SUM(CASE WHEN timestamp > '2016-04-20 09:40:241.213' THEN 1 ELSE 0 END) as cnt
FROM SavedScreenshotsLog
GROUP BY name
ORDER BY cnt DESC;
Note that this will run slower because there is no filter on the dates prior to aggregation.
CREATE TABLE #TEST (name varchar(100), dt datetime)
INSERT INTO #TEST VALUES ('someName','2016-04-20 09:41:41.213')
INSERT INTO #TEST VALUES ('someName','2016-04-20 09:41:41.213')
INSERT INTO #TEST VALUES ('anotherName','2016-04-20 09:43:41.213')
declare #YourDatetime datetime = '2016-04-20 09:41:41.213'
SELECT name, count(dt)
FROM #TEST
WHERE dt >= #YourDatetime
GROUP BY name
I've posted the answer, because using the above query can generate errors in converting the string in where clause into a datetime, it depends on the format of the datetime.

Query SQL Searching inside value

I've a database that's looking simular like this:
--------------------------------------------------------------------------|
| PKey | name | date | Snippet |
--------------------------------------------------------------------------|
| 1 | Harry |2016-05-03|<menu><emp1>1</emp1><emp2>2</emp2></menu>|
--------------------------------------------------------------------------|
| 2 | Barry |2016-05-03|<menu><emp1>7</emp1><emp2>0</emp2></menu>|
--------------------------------------------------------------------------|
| 3 | Tarry |2016-05-01|<menu><emp1>3</emp1><emp2>6</emp2></menu>|
--------------------------------------------------------------------------|
What I'm tryin to do is searching inside the "Snippet" like :
SELECT Pkey, Snippet.value('(/Snippet/emp2)[1]', 'varchar(max)')
FROM *name* (NOLOCK)
WHERE date >= '2016-05-02'
AND date <= '2016-05-04'
AND Snippet.value('(/Snippet/emp2)[1]', 'varchar(max)') >= '1'
What I expect is PKey 1 because he is between the dates and emp 2 is bigger than 1 unlike PKey 2.
Still I din't get any result.
Does anyone knows what I'm doing (or thinking) wrong?
thanks in advanced.
The XQuery Path doesn't look correct as the root node in your xml is menu not snippet. Can you try updating the path to
Snippet.value('(/menu/emp2)[1]', 'varchar(max)')

SQL concat rows with same name value

Let say I got table like that
Name | Stage | Date
-------------------
A | 1st | 03092014
A | 2nd | 04092014
A | 3rd | 05092014
B | 1st | 06092014
B | 2nd | 08092014
C | 1st | 03092014
I wonder how to write SQL code wich would concat rows with same names and I will get something like that
Name | Stage | Date
----------------------+-----------------------------
A | 1st , 2nd, 3rd | 03092014 04092014 05092014
B | 1st, 2nd | 06092014 08092014
C | 1st | 03092014
Do I need to run through table with for cycle or is there better way to do that?
UPD:
I found out that I need to use this queries in Excel
You can use GROUP_CONCAT for this:
SELECT Name
, GROUP_CONCAT(Stage) AS Stages
, GROUP_CONCAT(Date) AS Dates
FROM my_table
GROUP BY Name;
With respect to your question - I am assuming you are using MS SQL Server 2008 or higher to get he desired output
I would suggest to use CROSS APPLY here to concat the data -
Assumed Your Table name - temptable
SELECT distinct tblMain.Name, substring(stages, 1, len(stages)-1) as [Stage],substring(dates, 1, len(dates)-1) as [Date]
FROM temptable tblMain
CROSS APPLY (
SELECT LTRIM(RTRIM(Stage)) + ','
FROM temptable tblDup1 WITH(NOLOCK)
WHERE tblDup1.Name= tblMain.Name
FOR XML PATH('')
) t1 (stages)
CROSS APPLY (
SELECT LTRIM(RTRIM(Date)) + ' '
FROM temptable tblDup2 WITH(NOLOCK)
WHERE tblDup2.Name= tblMain.Name
FOR XML PATH('')
) t2 (dates)
Working FIDDLE OUTPUT

Query XML File uploaded to single column in SQL Server

I am trying to learn XQuery and Xpath in SQL Server
I created a sample file and uploaded it to a Table with 2 columns ID, XMLDoc. The below code is within the document in the XMLDoc column so it is the only record in the column.
I am trying to query the file so it will show all the results in a table like a normal select statement would. How would you construct the select statement to select all the information like a select * ? How would you select one field like all suppliers? I would like to select the supplier, requestor for each item.
Here is the xml:
<tst:Document xmlns:tst ="http://www.w3.org/2001/XMLSchema" SchemaVersion="0.1" Classification="Test" UniqueIdentifier="1234" Title="Test">
<tst:Revision RevNumber="0" TimeStamp="2013-01-21T12:56:00">
<tst:Author Name="Me" Guid="1234" />
</tst:Revision>
<tst:Formats>
<tst:A12 Item="1">
<tst:Requestor Name="ADC" />
<tst:Supplier Name="BBC" />
<tst:Code>B</tst:Code>
<tst:IsRequirement>true</tst:IsRequirement>
<tst:IsNotRequired>false</tst:IsInformation>
<tst:Remarks>ADC (Random Input Section)</tst:Remarks>
<tst:Notes>Next Round.</tst:Notes>
<tst:Events>
<tst:SubTest Item="0">
<tst:BLDG>BLDG1</tst:BLDG>
<tst:BLDG2>BLDG2</tst:BLDG2>
<tst:Function>Testing</tst:Function>
<tst:Desciption>Normal Flow</tst:Desciption>
</tst:SubTest>
</tst:Events>
<tst:IsReady>true</tst:IsReady>
<tst:IsNotReady>false</tst:IsNotReady>
</tst:A12>
<tst:A12 Item="2">
<tst:Requestor Name="ADC" />
<tst:Supplier Name="BBC" />
<tst:Code>A</tst:Code>
<tst:IsRequirement>true</tst:IsRequirement>
<tst:IsInformation>false</tst:IsInformation>
<tst:Remarks>Requirement Not yet met.</tst:Remarks>
<tst:Notes>Ready.</tst:Notes>
<tst:Events>
<tst:SubTest Item="0">
<tst:BLDG>BLDG3</tst:BLDG>
<tst:BLDG2>BLDG4</tst:BLDG2>
<tst:TotalEvents>1</tst:TotalEvents>
<tst:Function>Development</tst:Function>
<tst:Desciption>Process Flow</tst:Desciption>
</tst:SubTest>
</tst:Events>
<tst:IsReady>true</tst:IsReady>
<tst:IsNotReady>false</tst:IsNotReady>
</tst:A12>
</tst:Formats>
</tst:Document>
Query I ran
I just got a return, but it is still showing it in xml form:
Select XMLDoc.query('/*/*/*/*[local-name()=("Requestor", "Supplier")]')
From XMLLoad
I Updated the xml snippet, sry had a typo! It will load now
INSERT INTO TableName(ColumnName)
SELECT * FROM OPENROWSET(
BULK 'C:\Users\Filepath.xml',
SINGLE_BLOB) AS x;
SQL Fiddle
MS SQL Server 2008 Schema Setup:
create table XMLDoc (XMLLoad xml);
insert into XMLDoc(XMLLoad) values('
<tst:Document xmlns:tst ="http://www.w3.org/2001/XMLSchema" SchemaVersion="0.1" Classification="Test" UniqueIdentifier="1234" Title="Test">
<tst:Revision RevNumber="0" TimeStamp="2013-01-21T12:56:00">
<tst:Author Name="Me" Guid="1234" />
</tst:Revision>
<tst:Formats>
<tst:A12 Item="1">
<tst:Requestor Name="ADC" />
<tst:Supplier Name="BBC" />
<tst:Code>B</tst:Code>
<tst:IsRequirement>true</tst:IsRequirement>
<tst:IsInformation>false</tst:IsInformation>
<tst:Remarks>ADC (Random Input Section)</tst:Remarks>
<tst:Notes>Next Round.</tst:Notes>
<tst:Events>
<tst:SubTest Item="0">
<tst:BLDG>BLDG1</tst:BLDG>
<tst:BLDG2>BLDG2</tst:BLDG2>
<tst:Function>Testing</tst:Function>
<tst:Desciption>Normal Flow</tst:Desciption>
</tst:SubTest>
</tst:Events>
<tst:IsReady>true</tst:IsReady>
<tst:IsNotReady>false</tst:IsNotReady>
</tst:A12>
<tst:A12 Item="2">
<tst:Requestor Name="ADC" />
<tst:Supplier Name="BBC" />
<tst:Code>A</tst:Code>
<tst:IsRequirement>true</tst:IsRequirement>
<tst:IsInformation>false</tst:IsInformation>
<tst:Remarks>Requirement Not yet met.</tst:Remarks>
<tst:Notes>Ready.</tst:Notes>
<tst:Events>
<tst:SubTest Item="0">
<tst:BLDG>BLDG3</tst:BLDG>
<tst:BLDG2>BLDG4</tst:BLDG2>
<tst:TotalEvents>1</tst:TotalEvents>
<tst:Function>Development</tst:Function>
<tst:Desciption>Process Flow</tst:Desciption>
</tst:SubTest>
</tst:Events>
<tst:IsReady>true</tst:IsReady>
<tst:IsNotReady>false</tst:IsNotReady>
</tst:A12>
</tst:Formats>
</tst:Document>');
Query 1:
with xmlnamespaces('http://www.w3.org/2001/XMLSchema' as tst)
select A12.X.value('#Item', 'int') as A12,
A12.X.value('tst:Requestor[1]/#Name', 'varchar(25)') as Requestor,
A12.X.value('tst:Supplier[1]/#Name', 'varchar(25)') as Supplier,
A12.X.value('(tst:Code/text())[1]', 'varchar(25)') as Code,
A12.X.value('(tst:IsRequirement/text())[1]', 'bit') as IsRequirement,
A12.X.value('(tst:IsInformation/text())[1]', 'bit') as IsInformation,
A12.X.value('(tst:Remarks/text())[1]', 'varchar(50)') as Remarks,
A12.X.value('(tst:Notes/text())[1]', 'varchar(50)') as Notes,
ST.X.value('#Item', 'int') as SubTest,
ST.X.value('(tst:BLDG/text())[1]', 'varchar(25)') as BLDG,
ST.X.value('(tst:BLDG2/text())[1]', 'varchar(25)') as BLDG2,
ST.X.value('(tst:TotalEvents/text())[1]', 'int') as TotalEvents,
ST.X.value('(tst:Function/text())[1]', 'varchar(25)') as [Function],
ST.X.value('(tst:Desciption/text())[1]', 'varchar(50)') as Desciption
from XMLDoc as X
cross apply X.XMLLoad.nodes('/tst:Document/tst:Formats/tst:A12') as A12(X)
cross apply A12.X.nodes('tst:Events/tst:SubTest') as ST(X)
Results:
| A12 | REQUESTOR | SUPPLIER | CODE | ISREQUIREMENT | ISINFORMATION | REMARKS | NOTES | SUBTEST | BLDG | BLDG2 | TOTALEVENTS | FUNCTION | DESCIPTION |
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
| 1 | ADC | BBC | B | 1 | 0 | ADC (Random Input Section) | Next Round. | 0 | BLDG1 | BLDG2 | (null) | Testing | Normal Flow |
| 2 | ADC | BBC | A | 1 | 0 | Requirement Not yet met. | Ready. | 0 | BLDG3 | BLDG4 | 1 | Development | Process Flow |
Check out value() and nodes().