May 1, 2018 at 4:57 pm
This is my 4th day on SQL so I am a newbie. I created a query to import from an xml file. It works but I am having trouble dumping it to a table. Everywhere I look examples are adding the data in the query and not from the query results (memory). Here is basically what I am trying to do.
Code I have to import file.
DECLARE @x xml
SELECT @x=P
FROM OPENROWSET (BULK 'C:/proscore5/3WomenResultsDay1.xml', SINGLE_BLOB) AS Product(P)
DECLARE @hdoc int
EXEC sp_xml_preparedocument @hdoc OUTPUT, @x
SELECT*
FROM OPENXML (@hdoc, '/MeetResultsMsg/AthleteResults/Athlete/Scores/Score', 1)
WITH(
FirstName varchar(100) '../../@FirstName',
LastName varchar(100) '../../@LastName',
AgeGroup varchar(100) '../../@AG',
CompNumber int '../../@CompNum',
event varchar(100),
avgscore float,
bscore float)
ORDER BY AgeGroup DESC
,event ASC
,avgscore DESC
Sample of my data. Each xml file has about 50 to 80 records.
<?xml version="1.0" encoding="ISO-8859-1"?>
<MeetResultsMsg Type="ARTW3" EventID="" Session="1" >
<AthleteResults>
<Athlete Type="ARTW3" CompNum="333" LastName="Mockford" FirstName="Holly" AG="SRA">
<Scores>
<Score event="1" avgscore="9.200" bscore="9.200">
<JudgeScore id="1" score="9.200"/>
<JudgeScore id="2" score="9.200"/>
</Score>
<Score event="2" avgscore="9.250" bscore="9.250">
<JudgeScore id="1" score="9.250"/>
<JudgeScore id="2" score="9.250"/>
</Score>
<Score event="3" avgscore="9.375" bscore="9.375">
<JudgeScore id="1" score="9.450"/>
<JudgeScore id="2" score="9.300"/>
</Score>
<Score event="4" avgscore="9.500" bscore="9.500">
<JudgeScore id="1" score="9.600"/>
<JudgeScore id="2" score="9.400"/>
</Score>
<Score event="AA" avgscore="37.325"/>
</Scores>
<Places>
<Place event="AA" rank="1" order="1"/>
<Place event="1" rank="13" order="13"/>
<Place event="2" rank="8" order="8"/>
<Place event="3" rank="1" order="1"/>
<Place event="4" rank="1" order="1"/>
</Places>
</Athlete>
</AthleteResults>
</MeetResultsMsg>
So basically this is for scoring gymnastics meets. We have software that spits out the xml and updates it every 5 sec. We need to import the data and break it up by Age Groups(AG). I am figuring it out step by step but I am stuck getting it into a database/table. Any help would be appreciated.
Tim
May 2, 2018 at 1:52 am
When you say you want to get it into the database what do you mean? SQL Server has an xml datatype, so do you mean simply store the xml in a table with a column of that datatype? That would just need a simple INSERT statement.
Thom~
Excuse my typos and sometimes awful grammar. My fingers work faster than my brain does.
Larnu.uk
May 2, 2018 at 1:55 am
DECLARE @x xml
CREATE TABLE WomenResults
(
FirstName varchar(100),
LastName varchar(100),
AgeGroup varchar(100) ,
CompNumber int,
event varchar(100),
avgscore float,
bscore float
)
SELECT @x=P
FROM OPENROWSET (BULK 'C:/proscore5/3WomenResultsDay1.xml', SINGLE_BLOB) AS Product(P)
DECLARE @hdoc int
EXEC sp_xml_preparedocument @hdoc OUTPUT, @x
INSERT INTO WomenResults
SELECT*
FROM OPENXML (@hdoc, '/MeetResultsMsg/AthleteResults/Athlete/Scores/Score', 1)
WITH(
FirstName varchar(100) '../../@FirstName',
LastName varchar(100) '../../@LastName',
AgeGroup varchar(100) '../../@AG',
CompNumber int '../../@CompNum',
event varchar(100),
avgscore float,
bscore float)
ORDER BY AgeGroup DESC
,event ASC
,avgscore DESC
Then you will need to deal with updates, inserts, deletes (do it to another table, then you aren't reading the xml more than once).
May 2, 2018 at 10:24 am
Ok so I need to declare the table first. Here is how the program works. There is the main scoring software that the judges enter the individual scores for. The company that made the software has a script that output the results via xml. You can change the time from 1sec to 300sec for the updates but it either rewrites the entire xml and replaces the old one with the same name or it opens the xml and makes the changes. Since I do not know how it is done I will need to read the same file multiple times. Should I put in a condition before I create the table to verify there is a table and it has data in it, or should I use this one script to create the first tables and then execute another one that leave the table creating out?
Thank you for your input
Tim
May 2, 2018 at 10:30 am
TheFirstOne - Tuesday, May 1, 2018 4:57 PMThis is my 4th day on SQL so I am a newbie. I created a query to import from an xml file. It works but I am having trouble dumping it to a table. Everywhere I look examples are adding the data in the query and not from the query results (memory). Here is basically what I am trying to do.
- Import from an xml file every 5 seconds
- dump the results to the database/table
- the database/table is updated every 5 sec
- Each age group is output to a separate JSON/xml file.
Code I have to import file.
DECLARE @x xmlSELECT @x=P
FROM OPENROWSET (BULK 'C:/proscore5/3WomenResultsDay1.xml', SINGLE_BLOB) AS Product(P)DECLARE @hdoc int
EXEC sp_xml_preparedocument @hdoc OUTPUT, @x
SELECT*
FROM OPENXML (@hdoc, '/MeetResultsMsg/AthleteResults/Athlete/Scores/Score', 1)
WITH(
FirstName varchar(100) '../../@FirstName',
LastName varchar(100) '../../@LastName',
AgeGroup varchar(100) '../../@AG',
CompNumber int '../../@CompNum',
event varchar(100),
avgscore float,
bscore float)ORDER BY AgeGroup DESC
,event ASC
,avgscore DESCSample of my data. Each xml file has about 50 to 80 records.
<?xml version="1.0" encoding="ISO-8859-1"?>
<MeetResultsMsg Type="ARTW3" EventID="" Session="1" >
<AthleteResults>
<Athlete Type="ARTW3" CompNum="333" LastName="Mockford" FirstName="Holly" AG="SRA">
<Scores>
<Score event="1" avgscore="9.200" bscore="9.200">
<JudgeScore id="1" score="9.200"/>
<JudgeScore id="2" score="9.200"/>
</Score>
<Score event="2" avgscore="9.250" bscore="9.250">
<JudgeScore id="1" score="9.250"/>
<JudgeScore id="2" score="9.250"/>
</Score>
<Score event="3" avgscore="9.375" bscore="9.375">
<JudgeScore id="1" score="9.450"/>
<JudgeScore id="2" score="9.300"/>
</Score>
<Score event="4" avgscore="9.500" bscore="9.500">
<JudgeScore id="1" score="9.600"/>
<JudgeScore id="2" score="9.400"/>
</Score>
<Score event="AA" avgscore="37.325"/>
</Scores>
<Places>
<Place event="AA" rank="1" order="1"/>
<Place event="1" rank="13" order="13"/>
<Place event="2" rank="8" order="8"/>
<Place event="3" rank="1" order="1"/>
<Place event="4" rank="1" order="1"/>
</Places>
</Athlete>
</AthleteResults>
</MeetResultsMsg>So basically this is for scoring gymnastics meets. We have software that spits out the xml and updates it every 5 sec. We need to import the data and break it up by Age Groups(AG). I am figuring it out step by step but I am stuck getting it into a database/table. Any help would be appreciated.
Tim
Yes, I was looking at the insert command but all the examples I looked at on youtube had the data being
added within the query. The below modification worked.
May 2, 2018 at 10:59 am
I have been reading that it is not necessary to sort the table? Is that true. I was thinking of sorting the table by AgeGroup/event/avgscore and then outputting the table as an xml/json file which can then be read by the app software? I can sort the data with this in the query
SELECT FirstName, LastName, AgeGroup, CompNumber, event, avgscore, bscore
FROM WomenResults
ORDER BY AgeGroup, event, avgscore DESC;
but the table has the data just as it was in the file. The goal is the separate the athletes so the parents can view scoring by their daughters agegroup.
Tim
May 3, 2018 at 11:49 am
TheFirstOne - Wednesday, May 2, 2018 10:59 AMI have been reading that it is not necessary to sort the table? Is that true. I was thinking of sorting the table by AgeGroup/event/avgscore and then outputting the table as an xml/json file which can then be read by the app software? I can sort the data with this in the querySELECT FirstName, LastName, AgeGroup, CompNumber, event, avgscore, bscore
FROM WomenResults
ORDER BY AgeGroup, event, avgscore DESC;but the table has the data just as it was in the file. The goal is the separate the athletes so the parents can view scoring by their daughters agegroup.
Tim
Okay, but what, exactly, does "separate the athletes so the parents can view scoring by their daughter age group" mean? When you run a query, the results come back to you in SSMS as a grid or as text, depending on which way you have that tool configured. Using ORDER BY just determines which order the rows in the table are returned. As we only have data for what appears to be one athlete, there's not much testing we can do, nor do we have any idea what it means for you to be able to "show the parents" whatever you want to show them. What, exactly, do you do with the results of that query? Slap it into a spreadsheet and project a view of it onto a monitor somewhere? What about that scoring software? Does it provide some display capacity that could organize the data by age group? We need a lot more information...
Steve (aka sgmunson) 🙂 🙂 🙂
Rent Servers for Income (picks and shovels strategy)
May 3, 2018 at 7:36 pm
Ok, So here is a little more detail. We have a program (one that I cannot have access to the code) that runs the meets. Judges enter scores and tallies everything and at the end of the meet we print up reports and give out awards. This software output results on the fly to some vendors that repackage it to their web sites. Parents view the results on apps on their phones. Unfortunately our meets are in steel buildings and getting connections is difficult. Also you have to navigate through all meets in the US to find the one your are at. We want to bypass this slowness and broadcast the scores locally. While we do have score boards, the scores only last for 30 sec and we cannot show top scores in each event and age group. The software company that make the scoring program has a small program that output the scores in xml which they let NBC use in college and up so I have to make do with what I have. . I am not using SSMS I think, as I could not figure out how to install and make it work. It was easier to just write the code line by line. I coded html in the past and usually write in a text editor and not a package program. Here is what I have done up to date
Programming I need to do.
I am an old Access programmer so I downloaded Visual studio 2017 and plan to create a program to first delete any existing tables, create the new ones, add the data and output JSON files to a local web serer where our App can access. Our app will have a look up for either lastname, competition number or USAG number. They will then be able to see each events score and where they rank in their age group for each event.
Tim
May 4, 2018 at 1:43 am
Ok, let's start with the first bullet point: A query to create all the tables(QCreateTables).This implies you have DDL for your table(s). Could you post that please? We then know what the XML data needs to look like to be able to be inserted into those tables.
You also keep mention ion JSON, however, we've only seen XML so far. Which is it? If it's JSON, SQL Server 2014 is going to be a problem (JSON functions were only introduced with SQL Server 2016). JSON and XML are completely different, the acronyms are not interchangeable, so please don't say one when you mean the other.
Thom~
Excuse my typos and sometimes awful grammar. My fingers work faster than my brain does.
Larnu.uk
May 4, 2018 at 10:39 am
I am attaching the three queries I have which are not finished yet. The JSON is the format that the app designers want. Please remember this is my first week learning SQL so I need time to get up to speed. I was just assuming I could output to JSON with the 2014 version. Once again thank you for your input.
May 4, 2018 at 11:15 am
TheFirstOne - Friday, May 4, 2018 10:39 AMI was just assuming I could output to JSON with the 2014 version.
Unfortunately not: https://docs.microsoft.com/en-us/sql/relational-databases/json/json-data-sql-server?view=sql-server-2017. Notice that the topic applies to SQL Server (starting with 2016).If you have to be able to export to JSON you'll need to use a more recent version of SQL Server, or use a different tool which can integrate with SQL Server and export JSON.
I've only opened the first file, but that is a lot of tables there which seems to have the same DDL definition. This seems like a poor design choice. You shouldn't be separating data into separate tables because they are attached to a different event, or Age Group; doing so makes your solution non-scalable. You should be storing all the data in a single table and then using a column to denote the specific detail. If you then only need specific data, instead of querying the "correct" table, you simply use a WHERE clause. This is a common mistake by beginniners, however, it's something that you need to get out of the habit of doing very early on. You'll find, otherwise, that you'll be entering a "world of pain" in the future otherwise; especially if your data begins to change.
If you really need to do something more "drastic" (because you have a much larger amount of data), you can also look into Table Partitioning, however, that isn't something that I recommend for a beginning, nor for the amount of data you are likely to have,
To put this a little in perspective, one thing I've seen a lot of is people separate data for years into different tables. So their DDL definition looks something like:
The first problem here is you have 2 tables for 2 separate years. The other is that there's a repeating field for the item ID; meaning a single sale is not limited to 5 items; not great.
The DDL should really look like this:
This firstly means that the Sale table doesn't need to have a new one made every year. It also means you likely don't need to create dynamic SQL later down the line to query your data. As for the item, it now has a (what i refer to as) a composition key table. It's effectively just a list of foreign keys that link the Sale and Item tables, as they have a Many to Many relationship.
Of course, these are overly simplified; there's no Foreign keys or Primary keys for example. This, however, is one of the fundamental mind sets you need to use when designing tables in a Relational Database.
I haven't ventured too far into the text files, but i think we really need to start at the basics first and fix that problem before we even consider translating the XML into something but tabular.
Does the above make sense, and are you happy to entertain this?
Thom~
Excuse my typos and sometimes awful grammar. My fingers work faster than my brain does.
Larnu.uk
May 4, 2018 at 1:46 pm
Yes, I do want to code the most efficiently, just beginning like you said. So to start over here are the different tables I will have.
This table has all the data that the scoring software outputs in xml. There are 14 possible combinations. You can have multiple levels during a session so I would code a check box to select the levels. The level is in the Type variable. I was just going to create 14 different programs and then have a drop down box to select, not efficient but the best I have for now.
Level2,Level3,Level4,Level5,Level6,Level7,Level8,Level9,Level10,LevelXB,LevelXS,LevelXG,LevelXP,LevelXD
CREATE TABLE lvl3WomenResultsDay1
(
Type varchar(50),
CompNum int ,
FirstName varchar(50),
LastName varchar(50),
AgeGroup varchar(10),
event varchar(10),
avgscore float,
bscore float);
The next table is a list of all Athletes in the meet for all session. I am adding it as we may need the data in the future.
CREATE TABLE AthleteListDay1
(
Type varchar(50),
Session int,
Level varchar(10),
CompNum int,
USAGNum int,
FirstName varchar(50),
LastName varchar(50),
ClubName varchar(50)
)
The next table is to hold scores with the agegroup = "Child"
CREATE TABLE lvl3WomenResultsDay1Child(
FirstName varchar(50),
LastName varchar(50),
CompNum int ,
AgeGroup varchar(10),
event varchar(10),
avgscore float,
bscore float);
And then tables to hold the events plus the AA
CREATE TABLE lvl3WomenResultsDay1ChildEvent1Vault(
FirstName varchar(50),
LastName varchar(50),
CompNum int ,
AgeGroup varchar(10),
event varchar(10),
avgscore float,
bscore float);
CREATE TABLE lvl3WomenResultsDay1ChildEvent2Bars(
Type varchar(50),
CompNum int ,
FirstName varchar(50),
LastName varchar(50),
AgeGroup varchar(10),
event varchar(10),
avgscore float,
bscore float);
CREATE TABLE lvl3WomenResultsDay1ChildEvent3Beam(
FirstName varchar(50),
LastName varchar(50),
CompNum int ,
AgeGroup varchar(10),
event varchar(10),
avgscore float,
bscore float);
CREATE TABLE lvl3WomenResultsDay1ChildEvent4Floor(
FirstName varchar(50),
LastName varchar(50),
CompNum int ,
AgeGroup varchar(10),
event varchar(10),
avgscore float,
bscore float);
CREATE TABLE lvl3WomenResultsDay1ChildEventAA(
FirstName varchar(50),
LastName varchar(50),
CompNum int ,
AgeGroup varchar(10),
event varchar(10),
avgscore float,
bscore float);
Here are all the possible age groups
Child
Junior
Senior
JRA through Z
SRA through Z
I am attaching the correct text file for a level 3 meet. There is also a rotation import but is does not change and is not part of the scoring.
Tim
May 4, 2018 at 5:19 pm
So I think what your are saying is I need to just have one big table like QWomenResultsDay1 with all the records and then output each category to xml/csv/JSON so I would have a possible 29 output files. I would assume that I could skip any files that are NULL for agegroup as usually they only go up to JRC & SRC. The rest are for huge meets that we are not yet involved in. Usually we only see Child, Junior, Senior, JRA, JRB, JRC & SRA, SRB, SRC. There is the possibility for scorekeepers to makeup their own age groups but I do not know how to account for that.
1. QInputRecords
2. QWomensResultsDay1
WHILE (@AgeGroup !=Null)
IF AgeGroup = Child
BEGIN
Output all records for AG Vault
Output all records for AG Bars
Output all records for AG Beam
Output all records for AG Floor
Output all records for AG AA
END
ELSE IF AgeGroup = Junior
BEGIN
Output all records for AG Vault
Output all records for AG Bars
Output all records for AG Beam
Output all records for AG Floor
Output all records for AG A
END
....... and so on down the line. Then nest the whole thing in a loop controlled by a start and stop button to check for changes.
Tim
May 4, 2018 at 10:03 pm
I have reduced my 3 query's to the most basic data. From this I will need to output the xml/CSV/JSON files and also create a user interface to select which session it is in. I replaced lvl3 with an lvlx which I will get from the user input. I will need to pass this variable to the FROM OPENROWSET (BULK 'C:/proscore5/xWomenResultsDay1.xml', SINGLE_BLOB) AS Product(P).
QAthleteListDay1 (Still working on it)
QWomensResults
USE meetscoreslive
DECLARE @x xml
DROP TABLE lvlxWomenResultsDay1;
CREATE TABLE lvlxWomenResultsDay1(
Type varchar(10),
FirstName varchar(50),
LastName varchar(50),
AgeGroup varchar(50) ,
CompNum int,
event varchar(10),
avgscore float,
bscore float)
SELECT @x=P
FROM OPENROWSET (BULK 'C:/proscore5/test.xml', SINGLE_BLOB) AS Product(P)
DECLARE @hdoc int
EXEC sp_xml_preparedocument @hdoc OUTPUT, @x
INSERT INTO lvlxWomenResultsDay1
SELECT*
FROM OPENXML (@hdoc, '/MeetResultsMsg/AthleteResults/Athlete/Scores/Score', 1)
WITH(
Type varchar(10) '../../@Type',
FirstName varchar(50) '../../@FirstName',
LastName varchar(50) '../../@LastName',
AgeGroup varchar(50) '../../@AG',
CompNum int '../../@CompNum',
event varchar(10),
avgscore float,
bscore float)
SELECT Type FirstName, LastName, AgeGroup, CompNum, event, avgscore, bscore
FROM lvlxWomenResultsDay1
ORDER BY AgeGroup, event, avgscore DESC;
QCreateTables
USE meetscoreslive
CREATE TABLE lvlxWomenResultsDay1(
Type varchar(10),
FirstName varchar(50),
LastName varchar(50),
AgeGroup varchar(10) ,
CompNum int,
event varchar(10),
avgscore float,
bscore float)
QDropTables
USE meetscoreslive
DROP TABLE lvlxWomenResultsDay1;
My Results (Missing Headers)
ARTW3 Arcuino Child 319 1 9.45 9.45
ARTW3 Seed Child 340 1 8.85 8.85
ARTW3 Wayts Child 344 1 8.85 8.85
ARTW3 Robinson Child 339 1 8.85 8.85
ARTW3 Anderson Child 347 1 8.85 8.85
ARTW3 Anderson Child 348 1 8.85 8.85
May 7, 2018 at 10:37 am
You may want to consider a "normalized" table structure. Something along the lines of:CREATE TABLE dbo.Addresses (
AddressID int IDENTITY(1,1) NOT NULL PRIMARY KEY CLUSTERED,
AddressType char(1) NOT NULL, -- 'C' = Competitor, 'V' = Venue
AddressLine1 varchar(50) NOT NULL,
AddressLine2 varchar(50),
AddressLine3 varchar(50),
City varchar(30) NOT NULL,
StateAbbr char(2),
PostalCode varchar(10)
);
GO
CREATE TABLE dbo.Venues (
VenueID int IDENTITY(1,1) NOT NULL PRIMARY KEY CLUSTERED,
VenueDescription varchar(50) NOT NULL,
VenueAddressID int NOT NULL REFERENCES dbo.Addresses.AddressID
);
GO
CREATE TABLE dbo.EventList (
EventID int IDENTITY(1,1) NOT NULL PRIMARY KEY CLUSTERED,
EventName varchar(50) NOT NULL,
EventDT datetime,
EventDate AS CONVERT(date, EventDT) PERSISTED,
EventTime AS CONVERT(time, EventDT) PERSISTED,
EventDuration smallint, -- Number of minutes
VenueID int REFERENCES Venues.VenueID
);
GO
CREATE TABLE dbo.Competitors (
CompetitorID int IDENTITY(1,1) NOT NULL PRIMARY KEY CLUSTERED,
FirstName varchar(20) NOT NULL,
LastName varchar(20) NOT NULL,
FullName AS LastName + ', ' + FirstName PERSISTED NOT NULL,
CompetitorAddressID int REFERENCES dbo.Addresses.AddressID,
Gender char(1) NOT NULL, CONSTRAINT CK_Competitors_Gender_MF CHECK (Gender IN ('M', 'F')),
PhoneNumber varchar(10),
AlternatePhone varchar(10),
EMailAddress varchar(128)
);
GO
CREATE TABLE dbo.ParticipantList (
EventID int NOT NULL REFERENCES EventList.EventID,
CompetitorID int NOT NULL REFERENCES Competitors.CompetitorID,
HeatNumber tinyint NOT NULL,
CONSTRAINT PK_ParticipantList_EventID_CompetitorID PRIMARY KEY CLUSTERED
(
EventID ASC,
CompetitorID ASC,
HeatNumber ASC
)
);
GO
This kind of structure could make reporting a LOT easier to do, and help keep bad data out. You'd probably have to adapt it to your situation, but think of that as a learning opportunity.
Steve (aka sgmunson) 🙂 🙂 🙂
Rent Servers for Income (picks and shovels strategy)
Viewing 15 posts - 1 through 15 (of 127 total)
You must be logged in to reply to this topic. Login to reply