Dynamically generating HighCharts with SQL Server database - sql-server

I have a SQL Server database with columns ID, DateTime and Double.
For example:
001 | 2014:06:30 10:25AM | 101.5
001 | 2014:06:30 10:26AM | 102.5
001 | 2014:06:30 10:27AM | 111.5
002 | 2014:06:30 10:27AM | 101.4
002 | 2014:06:30 10:28AM | 123.1
003 | 2014:06:30 10:29AM | 114.9
003 | 2014:06:30 10:30AM | 171.6
003 | 2014:06:30 10:31AM | 131.2
003 | 2014:06:30 10:31AM | 119.4
I want my highcharts to be a scatter chart with Datetime values as the X-Axis and the Double Values as the Y-Axis. These values are on individual series which are defined by the ID column (i.e Series 001 will have 3 points).
The problem I'm having is that the ID Column can change. Based on the users selection my query is adjusting. In one instance I can have 5 series (5 different ID's) and in the example above only 3 series.
I was wondering how to create the series in a loop which will loop based on the unique ID's and to pass in the x and y values as arrays.
I've been trying to figure this out for a few days now and looked everywhere for a solution so anything helps at this moment. Currently I'm using Visual Studio 2013 and VB.Net with only a front and back end page. My data is in a MySQL Server where I'm already querying the values correctly based on user selection.

You could have SQL Server construct and return the array as a string
Declare #Table table (id varchar(10),SomeDate varchar(25),SomeValue money)
Insert into #Table values
('001','2014:06:30 10:25AM',101.5),
('001','2014:06:30 10:26AM',102.5),
('001','2014:06:30 10:27AM',111.5),
('002','2014:06:30 10:27AM',101.4),
('002','2014:06:30 10:28AM',123.1),
('003','2014:06:30 10:29AM',114.9),
('003','2014:06:30 10:30AM',171.6),
('003','2014:06:30 10:31AM',131.2),
('003','2014:06:30 10:31AM',119.4)
SELECT id, array = '['+STUFF((
SELECT ',["' + SomeDate+'",'+cast(SomeValue as varchar(25))+']' FROM #Table
WHERE id = x.id
FOR XML PATH(''), TYPE).value('.[1]', 'nvarchar(max)'), 1, 1, '')
+']'
FROM #Table AS x
GROUP BY ID
Returns
id array
001 [["2014:06:30 10:25AM",101.50],["2014:06:30 10:26AM",102.50],["2014:06:30 10:27AM",111.50]]
002 [["2014:06:30 10:27AM",101.40],["2014:06:30 10:28AM",123.10]]
003 [["2014:06:30 10:29AM",114.90],["2014:06:30 10:30AM",171.60],["2014:06:30 10:31AM",131.20],["2014:06:30 10:31AM",119.40]]

Related

SQL Server find sum of values based on criteria within another table

I have a table consisting of ID, Year, Value
---------------------------------------
| ID | Year | Value |
---------------------------------------
| 1 | 2006 | 100 |
| 1 | 2007 | 200 |
| 1 | 2008 | 150 |
| 1 | 2009 | 250 |
| 2 | 2005 | 50 |
| 2 | 2006 | 75 |
| 2 | 2007 | 65 |
---------------------------------------
I then create a derived, aggregated table consisting of an ID, MinYear, and MaxYear
---------------------------------------
| ID | MinYear | MaxYear |
---------------------------------------
| 1 | 2006 | 2009 |
| 2 | 2005 | 2007 |
---------------------------------------
I then want to find the sum of Values between the MinYear and MaxYear foreach ID in the aggregated table, but I am having trouble determining a proper query.
The final table should look something like this
----------------------------------------------------
| ID | MinYear | MaxYear | SumVal |
----------------------------------------------------
| 1 | 2006 | 2009 | 700 |
| 2 | 2005 | 2007 | 190 |
----------------------------------------------------
Right now I can perform all the joins to create the second table. But then I use a fast forward cursor to iterate through each record of the second table with the code inside the for loop looking like the following
DECLARE #curMin int
DECLARE #curMax int
DECLARE #curID int
FETCH Next FROM fastCursor INTo #curISIN, #curMin , #curMax
WHILE ##FETCH_STATUS = 0
BEGIN
SELECT Sum(Value) FROM ValTable WHERE Year >= #curMin and Year <= #curMax and ID = #curID
Group By ID
FETCH Next FROM fastCursor INTo #curISIN, #curMin , #curMax
Having found the sum of values between specified years, I can connect it back to the second table and I wind up the desired result (the third table).
However, the second table in reality is roughly 4 million rows, so this iteration is extremely time consuming (~generating 300 results a minute) and presumably not the best solution.
My question is, is there a way to generate the third table's results without having to use a cursor/for loop?
During a group by the sum will only be for the ID in question -- since the min year and max year is for the ID itself then you don't need to double query. The query below should give you exactly what you need. If you have a different requirement let me know.
SELECT ID, MIN(YEAR) as MinYear, MAX(YEAR) as MaxYear, SUM(VALUE) as SUMVALUE
FROM tablenameyoudidnotsay
GROUP BY ID
You could use query as bellow
TableA is your first table, and TableB is the second one
SELECT *,
(select SUM(Value) FROM TableA where tablea.ID=TableB.ID AND tableA.Year BETWEEN
TableB.MinYear AND TableB.MaxYear) AS SumValue
from TableB
You can put your criteria into a join and obtain the result all as one set which should be faster:
SELECT b.Id, b.MinYear, b.MaxYear, sum(a.Value)
FROM Table2 b
JOIN Table1 a ON a.Id=b.Id AND b.MinYear <= a.Year AND b.MaxYear >= a.Year
GROUP BY b.Id, b.MinYear, b.MaxYear

sum column with duplicates in another table

Wrong Result
So i have two tables
Order
Staging
Order Table having column structure
+-------+---------+-------------+---------------+----------+
| PO | cashAmt | ClaimNumber | TransactionID | Supplier |
+-------+---------+-------------+---------------+----------+
| 12345 | 100 | 99876 | abc123 | 0101 |
| 12346 | 50 | 99875 | abc123 | 0102 |
| 12345 | 100 | 99876 | abc123 | 0101 |
+-------+---------+-------------+---------------+----------+
Staging Table having column structure
+----------+------------+-------------+---------------+
| PONumber | paymentAmt | ClaimNumber | TransactionID |
+----------+------------+-------------+---------------+
| 12345 | 100 | 99876 | abc123 |
| 12346 | 50 | 99875 | abc123 |
+----------+------------+-------------+---------------+
The query i am executing is
select sum(cashAmt) CheckAmount, count(ClaimNumber) TotalLines
FROM [order] with (nolock)
WHERE TransactionID='abc123'
union
select sum(paymentAmt) CheckAmount, count(ClaimNumber) TotalLines
from Staging with (nolock)
where TransactionID='abc123'
but the sum is getting messed up because there is duplicate in one of the tables.
How can i edit that i get only uniques from the order table and the sums are correct
First ask yourself why are there duplicates in the Orders table? There must be a reason why they are there. I would deal with that first.
That issue aside, if the duplicates in the Orders table have a purpose and yet are not to be considered for this particular query, then you should be able to leave out the duplicates by simply changing the query to use DISTINCT on whatever field in the Orders table can reliably identify a duplicate.
select Distinct fieldname sum(cashAmt)... etc.
Assuming duplicates in your table are OK.
Not sure why you are using no lock, it seems like it shouldn't be included.
You could use a table variable to store the distinct values. You'll need to adjust the data types in the table variable to match your table structure.
I haven't tested the code below but it should look something like this.
DECLARE #OrderTmp TABLE (
cashAmt MyNumericColumn numeric(10,2)
, ClaimNumber int
, TransactionID Int
)
INSERT INTO #OrderTmp
select Distinct
cashAmt
,ClaimNumber
,TransactionID
FROM
[order]
WHERE TransactionID='abc123'
SELECT DISTINCT
select sum(cashAmt) CheckAmount, count(ClaimNumber) TotalLines
FROM #OrderTmp
where TransactionID='abc123'
union
select sum(paymentAmt) CheckAmount, count(ClaimNumber) TotalLines
from Staging
where TransactionID='abc123'

Unpivot SQL each row in SQL table to key-value pairs with group IDs

Running SQL Server 2012, I have a table in the following format:
ENC_ID | Name | ED_YN | Seq
-------------------------------------
1234 | John | Y | 1
1234 | Sally | N | 2
2345 | Chris | N | 1
2345 | Sally | N | 2
I would like to unpivot this into a entity-attribute-value list (if that's the right terminology - I am thinking of them as key-value pairs grouped by IDs), with the following format:
ENC_ID | Seq | Key | Value
--------------------------------------
1234 | 1 | Name | John
1234 | 1 | ED_YN | Y
1234 | 2 | Name | Sally
1234 | 2 | ED_YN | N
2345 | 1 | Name | Chris
2345 | 1 | ED_YN | N
2345 | 2 | Name | Sally
2345 | 2 | ED_YN | N
I have seen various answers to this using UNION or UNPIVOT, but these solutions tend to be long and must be closely customized to the table. I'm looking for a solution that can be reused without a great deal of rewriting as this pattern solves a problem I expect to run into frequently (ingesting data from star-schema into Tableau via extracts, where I don't necessarily know the number of value columns).
The closest thing I've found to solve this is this question/answer but I haven't had success altering the solution to add ENC_ID and Seq to each row in the result table.
Thanks.
I will use Cross Apply with table valued Constructor to do this unpivoting
select ENC_ID, Seq, Key, Value
from yourtable
cross apply
(values ('Name',Name),
('ED_YN',ED_YN)) CS (Key,Value)
You can try below query. This uses classic UNPIVOT syntax.
Since I am unsure about your column types I have casted both of them as varchar(100). You can increase length from 100.
Working sql fiddle demo link :
select enc_id,seq, k [key],v [value] from
(select enc_id,seq,cast(name as varchar(100)) as name, cast(ed_yn as varchar(100)) as ed_yn from r)s
UNPIVOT
( v for k in ([name],[ed_yn])
)up

PIVOT in SQL Server with no aggregate function

I have a table like this (lets call it T1):
Date | Category | Data
-------------------------------
2014-01-01 | 1 | 1.0
2014-01-01 | 2 | 2.0
2014-01-01 | 3 | 3.0
2014-01-02 | 1 | 4.0
2014-01-02 | 2 | 5.0
2014-01-02 | 3 | 6.0
Note that Data are floating point numbers, not sequential, I just made them that way so it's easier to see where they land up in the result. There is also a table translating the Category numbers to names (lets say (T2):
Category | Name
----------------
1 | A
2 | B
3 | C
And I would like a query that could return:
Date | B | C
---------------------------
2014-01-01 | 2.0 | 3.0
2014-01-02 | 5.0 | 6.0
I thought about trying with PIVOT which I haven't used before, however, I can't find a way to do it without using a aggregation function. But then I though that since I only actually have a single row per Date / Category combo using an aggregation like AVG should work. This is my try based on these docs:
SELECT [Date],
[2] as B,
[3] as C
FROM (SELECT * FROM T1 WHERE Category >= 2) AS SourceTable
PIVOT
(
AVG(Data)
FOR Category IN ([2], [3])
) AS PivotTable;
Which gets kind of close:
Date | B | C
---------------------------
2014-01-01 | 2.0 | NULL
2014-01-01 | NULL | 3.0
2014-01-02 | 5.0 | NULL
2014-01-02 | NULL | 6.0
But how do I get rid of the nulls and get all the same dates to be on the same row?
If you only have one value for each result, you can use any of the aggregate functions - eg: MAX
select * from
(select t.date, t.data,c.name from t1 t inner join category c on t.category = c.category) s
pivot (max(data) for name in ([b],[c])) p
The first part is the source data
select t.date, t.data,c.name from t1 t inner join category c on t.category = c.category
Then the pivot rearranges it, creating columns for the in values from the name column, and using the aggregate (max(data)) for the value in that column, which should give the desired results.
If you're getting nulls, it's probably from using select * in your source query, rather than selecting the required fields - ie: replace
SELECT * FROM T1 WHERE Category >= 2
with
select category, data FROM T1 WHERE Category >= 2

MS SQL SELECT INTO table auto generate unique identifier for every row

I try to create new table in MS SQL server 2008 using SELECT INTO statement. I want every row of the new table has auto-generated ID of UNIQUEIDENTIFIER type as a first column.
Code sample without ID column:
SELECT m.sellThru, m.turnover
INTO #tmp_table
FROM mpi m
Code template with ID (UNIQUEIDENTIFIER) column, I want to have as a result:
SELECT ?? as id, m.sellThru, m.turnover
INTO #tmp_table
FROM mpi m
Desired output is:
==============================================================
| id | sellThru | turnover |
==============================================================
| 6818F861-6E87-490D-AF5B-CA9A8B56212E | 155.25 | 110.25 |
--------------------------------------------------------------
| 1A2E8ED6-76A3-42F9-8A87-27050A2ECDC1 | 64.79 | 4.36 |
--------------------------------------------------------------
| B0F9F127-56BB-4E87-AC33-626BA13F7065 | 213.89 | 45.89 |
==============================================================
Any idea? Except IDENTITY(INT,1,1) or ROW_NUMBER() which is not want i want.
Easy:
select newID() as ID, *
into #temp
from YourTable

Resources