Unpivoting multiple, repeated columns with multiple (denormalized) values - sql-server

I have a table with multiple columns like this...
+-------+----------------+---------+---------+-----------+------------+-----------+-----------+------------+---------+-----------+------------+
| Name | Email | Address | Order1 | Shipping1 | Date1 | Order2 | Shipping2 | Date2 | Order3 | Shipping3 | Date3 |
+-------+----------------+---------+---------+-----------+------------+-----------+-----------+------------+---------+-----------+------------+
| John | john#abcd.com | 123 | Rock | 123 | 02/11/2017 | Computer | 123 | 07/11/2017 | Pen | 123 | 12/11/2017 |
| Jane | jane#abcd.com | 234 | Scissor | 234 | 03/11/2017 | Laptop | 234 | 08/11/2017 | Pencil | 234 | 13/11/2017 |
| Julie | julie#abcd.com | 345 | Paper | 345 | 04/11/2017 | Mouse | 345 | 09/11/2017 | Clips | 345 | 14/11/2017 |
| Jaden | jaden#abcd.com | 456 | Spock | 456 | 05/11/2017 | Screen | 456 | 10/11/2017 | Pins | 456 | 15/11/2017 |
| Jabba | jabba#abcd.com | 678 | Lizard | 678 | 06/11/2017 | Pen Drive | 678 | 11/11/2017 | Notepad | 678 | 16/11/2017 |
+-------+----------------+---------+---------+-----------+------------+-----------+-----------+------------+---------+-----------+------------+
And I want to unpivot the columns into rows like this in T-SQL...
+-------+----------------+---------+-----------+----------+------------+
| Name | Email | Address | Order | Shipping | Date |
+-------+----------------+---------+-----------+----------+------------+
| John | john#abcd.com | 123 | Rock | 123 | 02/11/2017 |
| John | john#abcd.com | 123 | Computer | 123 | 07/11/2017 |
| John | john#abcd.com | 123 | Pen | 123 | 12/11/2017 |
| Jane | jane#abcd.com | 234 | Scissor | 234 | 03/11/2017 |
| Jane | jane#abcd.com | 234 | Laptop | 234 | 08/11/2017 |
| Jane | jane#abcd.com | 234 | Pencil | 234 | 13/11/2017 |
| Julie | julie#abcd.com | 345 | Paper | 345 | 04/11/2017 |
| Julie | julie#abcd.com | 345 | Mouse | 345 | 09/11/2017 |
| Julie | julie#abcd.com | 345 | Clips | 345 | 14/11/2017 |
| Jaden | jaden#abcd.com | 456 | Spock | 456 | 05/11/2017 |
| Jaden | jaden#abcd.com | 456 | Screen | 456 | 10/11/2017 |
| Jaden | jaden#abcd.com | 456 | Pins | 456 | 15/11/2017 |
| Jabba | jabba#abcd.com | 678 | Lizard | 678 | 06/11/2017 |
| Jabba | jabba#abcd.com | 678 | Pen Drive | 678 | 11/11/2017 |
| Jabba | jabba#abcd.com | 678 | Notepad | 678 | 16/11/2017 |
+-------+----------------+---------+-----------+----------+------------+
I googled and checked other posts related to this but unable to get three values. :(
Appreciate the help!

You won't need to necessarily use UNPIVOT here at all.
You'll be able to UNION the three denormalized Orders back into a flattened output, like so:
SELECT name, Email, Address, Order1 AS Order, Shipping1 as Shipping, Date1 AS Date
FROM Table1
UNION ALL
SELECT name, Email, Address, Order2, Shipping2, Date2
FROM Table1
UNION ALL
SELECT name, Email, Address, Order3, Shipping3, Date3
FROM Table1
ORDER BY Name, Date;
SqlFiddle here
(The column names are set by the first select in the UNION, and the ORDER is applied to the final UNIONed data)

Related

Sum, Group by and Null

I'm dipping my toes into SQL. I have the following table
+------+----+------+------+-------+
| Type | ID | QTY | Rate | Name |
+------+----+------+------+-------+
| B | 1 | 1000 | 21 | Jack |
| B | 2 | 2000 | 12 | Kevin |
| B | 1 | 3000 | 24 | Jack |
| B | 1 | 1000 | 23 | Jack |
| B | 3 | 200 | 13 | Mary |
| B | 2 | 3000 | 12 | Kevin |
| B | 4 | 4000 | 44 | Chris |
| B | 4 | 5000 | 43 | Chris |
| B | 3 | 1000 | 26 | Mary |
+------+----+------+------+-------+
I don't know how I would leverage Sum and Group by to achieve the following result.
+------+----+------+------+-------+------------+
| Type | ID | QTY | Rate | Name | Sum of QTY |
+------+----+------+------+-------+------------+
| B | 1 | 1000 | 21 | Jack | 5000 |
| B | 1 | 3000 | 24 | Jack | Null |
| B | 1 | 1000 | 23 | Jack | Null |
| B | 2 | 3000 | 12 | Kevin | 5000 |
| B | 2 | 3000 | 12 | Kevin | Null |
| B | 3 | 200 | 13 | Mary | 1200 |
| B | 3 | 1000 | 26 | Mary | Null |
| B | 4 | 4000 | 44 | Chris | 9000 |
| B | 4 | 5000 | 43 | Chris | Null |
+------+----+------+------+-------+------------+
Any help is appreciated!
You can use window function :
select t.*,
(case when row_number() over (partition by type, id order by name) = 1
then sum(qty) over (partition by type, id order by name)
end) as Sum_of_QTY
from table t;

Sum in subquery for a group of numbers

We are trying to get a combined table where we also try to sum the volume.
Dateset right now:
+-------------+-----+------------+------------+--------+---------+
| Voorziening | BSN | Begindatum | Einddatum | Volume | Product |
+-------------+-----+------------+------------+--------+---------+
| 1000 | 1 | 1-1-2017 | 31-1-2017 | 50 | AAAA |
+-------------+-----+------------+------------+--------+---------+
| 1200 | 1 | 1-2-2017 | 31-3-2017 | 200 | AAAA |
+-------------+-----+------------+------------+--------+---------+
| 1250 | 1 | 1-4-2017 | 10-4-2017 | 90 | AAAA |
+-------------+-----+------------+------------+--------+---------+
| 1111 | 2 | 4-1-2017 | 10-1-2017 | 4 | AABB |
+-------------+-----+------------+------------+--------+---------+
| 1345 | 2 | 11-1-2017 | 29-1-2017 | 80 | AABB |
+-------------+-----+------------+------------+--------+---------+
| 2000 | 1 | 10-1-2017 | 31-1-2017 | 90 | CCCC |
+-------------+-----+------------+------------+--------+---------+
| 2190 | 1 | 1-2-2017 | 31-12-2017 | 100 | CCCC |
+-------------+-----+------------+------------+--------+---------+
What I want to achieve
+-------------+-----+------------+------------+--------+---------+
| Voorziening | BSN | Begindatum | Einddatum | Volume | Product |
+-------------+-----+------------+------------+--------+---------+
| 1000 | 1 | 1-1-2017 | 10-4-2017 | 340 | AAAA |
+-------------+-----+------------+------------+--------+---------+
| 2000 | 1 | 10-1-2017 | 31-12-2017 | 190 | CCCC |
+-------------+-----+------------+------------+--------+---------+
| 1111 | 2 | 4-1-2017 | 29-1-2017 | 84 | AABB |
+-------------+-----+------------+------------+--------+---------+
What i've got so for is the folowwing query:
SELECT min(b.Voorziening) as voorzieningsnummer
,a.BSN
,min(b.Begindatum) as mindatum
,MAX(b.Einddatum) AS maxdatum
,a.Productcode
,
(SELECT sum(Volume)
FROM Voorziening
)as totaal
FROM Voorziening a
INNER JOIN Voorziening b
ON a.BSN = b.BSN
AND a.Productcode = b.Productcode
GROUP BY a.BSN, a.Productcode
The result is gives me is this:
+-------------+-----+------------+------------+--------+
| Voorziening | BSN | Begindatum | Einddatum | Volume |
+-------------+-----+------------+------------+--------+
| 1000 | 1 | 1-1-2017 | 10-4-2017 | 424 |
+-------------+-----+------------+------------+--------+
| 1111 | 2 | 4-1-2017 | 29-1-2017 | 424 |
+-------------+-----+------------+------------+--------+
You guys can help me to get the sum right?
There isn't any reason to use JOIN. you can use aggregate function directly.
You can try this.
SELECT min(a.Voorziening) as voorzieningsnummer
,a.BSN
,min(a.Begindatum) as mindatum
,MAX(a.Einddatum) AS maxdatum
,a.Productcode
,SUM(a.Volume) Volume
FROM Voorziening a
GROUP BY a.BSN, a.Productcode
if you are using sql server 2008 or above version then just go ahead with PARTITION BY
SUM(Volume)over(Partition by Product order by Voorziening,another,another)

Need to update "orderby" column

I have a table test
+----+--+------+--+--+----------+--+--------------+
| ID | | Name | | | orderby | | processgroup |
+----+--+------+--+--+----------+--+--------------+
| 1 | | ABC | | | 10 | | 1 |
| 10 | | DEF | | | 12 | | 1 |
| 15 | | LMN | | | 1 | | 1 |
| 44 | | JKL | | | 4 | | 1 |
| 42 | | XYZ | | | 3 | | 2 |
+----+--+------+--+--+----------+--+--------------+
I want to update the orderby column in the sequence, I am expecting output like
+----+--+------+--+--+----------+--+--------------+
| ID | | Name | | | orderby | | processgroup |
+----+--+------+--+--+----------+--+--------------+
| 1 | | ABC | | | 1 | | 1 |
| 10 | | DEF | | | 2 | | 1 |
| 15 | | LMN | | | 3 | | 1 |
| 44 | | JKL | | | 4 | | 1 |
| 42 | | XYZ | | | 5 | | 1 |
+----+--+------+--+--+----------+--+--------------+
Logic behind this is when we have procesgroup as 1, orderby column should update as 1,2,3,4 and when procesgroup is 2 then update orderby as 5.
This might help you
;WITH CTE AS (
SELECT ROW_NUMBER() OVER (ORDER BY processgroup, ID ) AS SNO, ID FROM TABLE1
)
UPDATE TABLE1 SET TABLE1.orderby= CTE.SNO FROM CTE WHERE TABLE1.ID = CTE.ID

Values differences between days

I have a SQL Server 2005 table titled "Journeys" as follows:
+---------------+
| Journeys |
+---------------+
| JourneyID |
| PlateNumber |
| DepartureDate |
| DepartureKM |
| ArrivalDate |
| ArrivalKM |
+---------------+
The table contains the following sample data:
+------------+--------------+----------------+--------------+--------------+-----------+
| JOURNEYID | PLATENUMBER | DEPARTUREDATE | DEPARTUREKM | ARRIVALDATE | ARRIVALKM |
+------------+--------------+----------------+--------------+--------------+-----------+
| 1 | ABC-123 | 01-01-2015 | 10000 | 01-02-2015 | 10200 |
| 2 | ABC-123 | 01-02-2015 | 10210 | 01-03-2015 | 10500 |
| 3 | ABC-123 | 01-03-2015 | 10500 | 01-04-2015 | 10650 |
| 4 | ABC-123 | 01-04-2015 | 10607 | 01-05-2015 | 10900 |
| 5 | XYZ-999 | 01-15-2015 | 30200 | 01-16-2015 | 30400 |
| 6 | XYZ-999 | 01-16-2015 | 30405 | 01-17-2015 | 30600 |
| 7 | XYZ-999 | 01-17-2015 | 30600 | 01-18-2015 | 30750 |
| 8 | XYZ-999 | 01-18-2015 | 30752 | 01-19-2015 | 30920 |
+------------+--------------+----------------+--------------+--------------+-----------+
I want to generate a query that returns a the following results with an extra column named 'KMDifference' which is the difference between 'ArrivalKM' from last day and 'DepartureKM' from today.
Desired results:
+-------------+---------------+-------------+-------------+-----------+--------------+
| PlateNumber | DepartureDate | DepartureKM | ArrivalDate | ArrivalKM | KMDifference |
+-------------+---------------+-------------+-------------+-----------+--------------+
| ABC-123 | 01-01-2015 | 10000 | 01-02-2015 | 10200 | 0 |
| ABC-123 | 01-02-2015 | 10210 | 01-03-2015 | 10500 | 10 |
| ABC-123 | 01-03-2015 | 10500 | 01-04-2015 | 10650 | 0 |
| ABC-123 | 01-04-2015 | 10607 | 01-05-2015 | 10900 | 7 |
| XYZ-999 | 01-15-2015 | 30200 | 01-16-2015 | 30400 | 0 |
| XYZ-999 | 01-16-2015 | 30405 | 01-17-2015 | 30600 | 5 |
| XYZ-999 | 01-17-2015 | 30600 | 01-18-2015 | 30750 | 0 |
| XYZ-999 | 01-18-2015 | 30752 | 01-19-2015 | 30920 | 2 |
+-------------+---------------+-------------+-------------+-----------+--------------+
See this SQL Fiddle here: http://sqlfiddle.com/#!3/28abd
You can use the following CTE based query in order to simulate LAG function available from SQL Server 2012 onwards:
;WITH Journeys_rn AS (
SELECT JourneyID, PlateNumber, DepartureDate, DepartureKM, ArrivalDate, ArrivalKM,
ROW_NUMBER() OVER(PARTITION BY PlateNumber ORDER BY DepartureDate) AS rn
FROM Journeys
)
SELECT j1.PlateNumber, j1.DepartureDate, j1.DepartureKM,
j1.ArrivalDate, j1.ArrivalKM,
j1.DepartureKM - ISNULL(j2.ArrivalKM, j1.DepartureKM) AS KMDifference
FROM Journeys_rn AS j1
LEFT JOIN Journeys_rn AS j2 ON j1.rn = j2.rn+1 AND j1.PlateNumber = j2.PlateNumber
j2.ArrivalKM in the above query is the value from previous record. ISNULL is needed so that a 0 value is calculated for the first record of each group.
SQL Fiddle Demo
P.S. The sample data in the OP do not match with the sample data of the SQL Fiddle source also provided in the OP. So had to fix it in order to get the desired reult set.

Magento database: Invoice items database table?

Does anyone know where the Invoice data is stored in Magento database?
For example, I've found that the order data is stored in sales_order, sales_flat_order, sales_flat_order_item.
I've also found out that the main invoice data is stored in sales_order_entity, sales_order_entity_decimal and sales_order_entity_int. Through that I can change the subtotal and totals of the invoice in the system.
But! I don't know where to find the items data? For orders, that data is in sales_flat_order_item, but my sales_flat_invoice_item table is empty?!
http://img809.imageshack.us/img809/1921/invoicey.jpg
I will tell you what I know for 1.4.0.1 which is the version i currently develop for, it may or may not be the same for whatever version you are using.
Also, why are you in the database anyways? Magento has made models for you to use so that you don't have to work in the database. Regardless I will describe how I find whatever attribute I'm looking for ...
For starters I'm assuming that your already logged into the database via a mysql client, run
SELECT `entity_type_id`,`entity_type_code`,`entity_table` FROM `eav_entity_type`
which will get you something like ...
+----------------+----------------------+----------------------------------+
| entity_type_id | entity_type_code | entity_table |
+----------------+----------------------+----------------------------------+
| 1 | customer | customer/entity |
| 2 | customer_address | customer/address_entity |
| 3 | catalog_category | catalog/category |
| 4 | catalog_product | catalog/product |
| 5 | quote | sales/quote |
| 6 | quote_item | sales/quote_item |
| 7 | quote_address | sales/quote_address |
| 8 | quote_address_item | sales/quote_entity |
| 9 | quote_address_rate | sales/quote_entity |
| 10 | quote_payment | sales/quote_entity |
| 11 | order | sales/order |
| 12 | order_address | sales/order_entity |
| 13 | order_item | sales/order_entity |
| 14 | order_payment | sales/order_entity |
| 15 | order_status_history | sales/order_entity |
| 16 | invoice | sales/order_entity |
| 17 | invoice_item | sales/order_entity |
| 18 | invoice_comment | sales/order_entity |
| 19 | shipment | sales/order_entity |
| 20 | shipment_item | sales/order_entity |
| 21 | shipment_comment | sales/order_entity |
| 22 | shipment_track | sales/order_entity |
| 23 | creditmemo | sales/order_entity |
| 24 | creditmemo_item | sales/order_entity |
| 25 | creditmemo_comment | sales/order_entity |
+----------------+----------------------+----------------------------------+
We want to know more about the "invoice_item" entity so lets see what attributes it has ... run
SELECT `attribute_id`,`entity_type_id`,`attribute_code`,`backend_type` FROM `eav_attribute` WHERE `entity_type_id`=17;
and you'll get something like ...
+--------------+----------------+----------------------------------+--------------+
| attribute_id | entity_type_id | attribute_code | backend_type |
+--------------+----------------+----------------------------------+--------------+
| 349 | 17 | additional_data | text |
| 340 | 17 | base_cost | decimal |
| 346 | 17 | base_discount_amount | decimal |
| 345 | 17 | base_price | decimal |
| 679 | 17 | base_price_incl_tax | decimal |
| 348 | 17 | base_row_total | decimal |
| 681 | 17 | base_row_total_incl_tax | decimal |
| 347 | 17 | base_tax_amount | decimal |
| 567 | 17 | base_weee_tax_applied_amount | decimal |
| 568 | 17 | base_weee_tax_applied_row_amount | decimal |
| 579 | 17 | base_weee_tax_disposition | decimal |
| 580 | 17 | base_weee_tax_row_disposition | decimal |
| 337 | 17 | description | text |
| 342 | 17 | discount_amount | decimal |
| 336 | 17 | name | varchar |
| 334 | 17 | order_item_id | int |
| 333 | 17 | parent_id | static |
| 341 | 17 | price | decimal |
| 678 | 17 | price_incl_tax | decimal |
| 335 | 17 | product_id | int |
| 339 | 17 | qty | decimal |
| 344 | 17 | row_total | decimal |
| 680 | 17 | row_total_incl_tax | decimal |
| 338 | 17 | sku | varchar |
| 343 | 17 | tax_amount | decimal |
| 571 | 17 | weee_tax_applied | text |
| 569 | 17 | weee_tax_applied_amount | decimal |
| 570 | 17 | weee_tax_applied_row_amount | decimal |
| 577 | 17 | weee_tax_disposition | decimal |
| 578 | 17 | weee_tax_row_disposition | decimal |
+--------------+----------------+----------------------------------+--------------+
the last column (backend_type) combined with the table for the entity (entity_table) is where the attribute for that entity will be so attribute "additional_data" should be in sales_order_entity_text with an attribute_id of 349.
Armed with this information now we just need to find an invoice, I'll use an example from a test install of mine. Lets look for the "base_price" of an invoice item.
First lets find all the items that are associated to the invoice (in my case invoice entity_id of 1303954)
SELECT * FROM `sales_order_entity` WHERE `entity_type_id`=17 AND `parent_id`=1303954;
which gives 2 items
+-----------+----------------+------------------+--------------+-----------+----------+---------------------+---------------------+-----------+
| entity_id | entity_type_id | attribute_set_id | increment_id | parent_id | store_id | created_at | updated_at | is_active |
+-----------+----------------+------------------+--------------+-----------+----------+---------------------+---------------------+-----------+
| 1303955 | 17 | 0 | | 1303954 | NULL | 2011-06-01 14:10:48 | 2011-06-01 14:10:48 | 1 |
| 1303956 | 17 | 0 | | 1303954 | NULL | 2011-06-01 14:10:48 | 2011-06-01 14:10:48 | 1 |
+-----------+----------------+------------------+--------------+-----------+----------+---------------------+---------------------+-----------+
Lets choose the first one and find the 'base_price'
SELECT * FROM `sales_order_entity_decimal` WHERE `attribute_id`=345 AND `entity_id`=1303955;
Which gives us ....
+----------+----------------+--------------+-----------+---------+
| value_id | entity_type_id | attribute_id | entity_id | value |
+----------+----------------+--------------+-----------+---------+
| 7361390 | 17 | 345 | 1303955 | 31.2500 |
+----------+----------------+--------------+-----------+---------+
Which of course its just a simple update to change it.
Again if you can do it via a Magento model I would highly suggest you do it that way, but if manual is the only way to go then well I hope this helped :)

Resources