Transpose data using sql oracle - sql

I have following data in a table
+---------+-----+----------+
| Zip_ cd | id | assignmt.|
|---------+-----+----------+
| 1812 | 777 | S |
| 1812 | 111 | P |
| 1451 | 878 | S |
| 55 | 45 | x |
| 55 | 646 | T |
| 55 | 455 | Z |
+---------+-----+----------+
I want to transpose it as following
+---------+-----+----+---------+-----+----------+---------+-----+----------+
| Zip_ cd | id | ass| Zip_cd1 | id1 |assignmt1 | Zip_cd2 | id2 |assignmt3 |
+---------+-----+----+---------+-----+----------+---------+-----+----------+
| 1812 | 777 | S | 1812 | 111 | P | 1812 | 111 | P |
| 1451 | 878 | S | | | | | | |
| 55 | 45 | X | 55 | 646 | T | 55 | 455 | Z |
+---------+-----+----------+---------+----------+---------+-----+----------+
So, I basically want to transpose based on the zip code. If 2 rows have same zip code its needs to be in single row.

Another query using pivot functionality:
select *
from table_name
pivot ( max(id) id
, max(assignmt) assignmt
FOR assignmt IN ('S' S,
'P' P));
+---------+-------+------------+--------+------------+
| ZIP_ CD | S_ID | S_ASSIGNMT.| P_ID | P_ASSIGNMT.|
+---------+-------+------------+--------+------------+
| 1812 | 777 | S | 111 | P |
| 1451 | 878 | S | NULL | NULL |
+---------+-------+------------+--------+------------+

Related

Selecting the first instance of a vendor, part combination

I am trying to create an indicator for if a particular transaction was the first time a part was purchased from a particular vendor.
I have a dataset that looks like this:
| transaction_id | vendor_id | part_id | trans_date |
|:--------------:|:---------:|:-------:|:-----------------:|
| 9Bx*2Pc' | a | 873 | 10/12/2018 |
| 1Po.4Ot, | a | 473 | 4/22/2016 |
| 9Sk"7Kv/ | b | 123 | 7/23/2016 |
| 2Lz&7Hu& | a | 873 | 12/20/2017 |
| 8Lz)5Is# | b | 743 | 10/22/2016 |
| 5Sc'6Jl/ | a | 113 | 10/6/2016 |
| 0Ra&8Hb& | a | 653 | 10/4/2017 |
| 4Wc-8Of* | c | 333 | 8/3/2017 |
| 8Vv+9Yo/ | c | 333 | 12/7/2016 |
| 6Qh!1Ha- | c | 333 | 3/28/2017 |
| 2Ol%4Rs# | c | 333 | 5/2/2017 |
| 1Gg#8Cm% | c | 333 | 11/15/2016 |
| 0Lw(6Pv/ | d | 873 | 8/13/2017 |
| 1Gy/7Zw, | a | 443 | 10/12/2018 |
| 2Gz,4Gp. | b | 103 | 1/5/2018 |
| 5Dj)6Wc+ | a | 893 | 12/17/2016 |
| 5Hl-8Ds! | a | 903 | 12/8/2017 |
| 8Ws$3Vy* | b | 873 | 1/13/2018 |
What I am looking to do is determine if the transaction_id was the first time (sorted by trans_date), that the part_id was purchased from a vendor_id. I would imagine the ideal output to look like this:
| transaction_id | vendor_id | part_id | trans_date | first_time |
|:--------------:|:---------:|:-------:|:-----------------:|:----------:|
| 9Bx*2Pc' | a | 873 | 10/12/2018 | N |
| 1Po.4Ot, | a | 473 | 4/22/2016 | Y |
| 9Sk"7Kv/ | b | 123 | 7/23/2016 | Y |
| 2Lz&7Hu& | a | 873 | 12/20/2017 | Y |
| 8Lz)5Is# | b | 743 | 10/22/2016 | Y |
| 5Sc'6Jl/ | a | 113 | 10/6/2016 | Y |
| 0Ra&8Hb& | a | 653 | 10/4/2017 | Y |
| 4Wc-8Of* | c | 333 | 8/3/2017 | N |
| 8Vv+9Yo/ | c | 333 | 12/7/2016 | N |
| 6Qh!1Ha- | c | 333 | 3/28/2017 | N |
| 2Ol%4Rs# | c | 333 | 5/2/2017 | N |
| 1Gg#8Cm% | c | 333 | 11/15/2016 | Y |
| 0Lw(6Pv/ | d | 873 | 8/13/2017 | Y |
| 1Gy/7Zw, | a | 443 | 10/12/2018 | Y |
| 2Gz,4Gp. | b | 103 | 1/5/2018 | Y |
| 5Dj)6Wc+ | a | 893 | 12/17/2016 | Y |
| 5Hl-8Ds! | a | 903 | 12/8/2017 | Y |
| 8Ws$3Vy* | b | 873 | 1/13/2018 | Y |
So far, I have tried (which was influenced by this post):
WITH
first_instance AS (
SELECT
tbl_trans.*,
ROW_NUMBER() OVER (PARTITION BY vendor_id||part_id ORDER BY trans_date) AS row_nums
FROM
tbl_trans
)
SELECT
x.*,
CASE WHEN y.row_nums = 1 THEN 'Y' ELSE 'N' END AS first_time_indicator
FROM
tbl_trans x
LEFT JOIN first_instance y
But I am met with:
ORA-00905: missing keyword
I have created a SQL FIDDLE with this data and the query thus far for testing. How can I determine the if a transaction was a first time purchase for a part/vendor combination?
Use window functions:
select t.*,
(case when row_number() over (partition by vendor_id, part_id order by trans_date) = 1
then 'Y' else 'N'
end) as first_time
from tbl_trans t;
You don't need a join.
Apart from row_number, there are multiple ways of achieving the desired result using analytical function as follows.
You can use first_value analytical function as follows:
Select t.*,
Case
when first_value(trans_date)
over (partition by vendor_id, part_id order by trans_date) = trans_date
then 'Y'
else 'N'
end as first_time
From your_table t;
The same way, you can also use min as follows:
Select t.*,
Case
when min(trans_date)
over (partition by vendor_id, part_id) = trans_date
then 'Y'
else 'N'
end as first_time
From your_table t;

SQL: FIter rows with specyfic pattern

I'm a bit new in sql.
I have the following table:
+-----+---------+------------------------+
| ID | ID_TEST | FILE_PATH |
+-----+---------+------------------------+
| 575 | 3 | Landscapes_001_h_A.jpg |
| 576 | 3 | Landscapes_001_h_B.jpg |
| 577 | 3 | Landscapes_001_h_C.jpg |
| 578 | 3 | Landscapes_001_h_D.jpg |
| 579 | 3 | Landscapes_001_h_E.jpg |
| 580 | 3 | Landscapes_002_h_A.jpg |
| 581 | 3 | Landscapes_002_h_B.jpg |
| 582 | 3 | Landscapes_002_h_C.jpg |
| 583 | 3 | Landscapes_002_h_D.jpg |
| 584 | 3 | Landscapes_002_h_E.jpg |
+-----+---------+------------------------+
The pattern for picture is Landscapes_XXX_h_Y.jpg
where
XXX is number from 1 to 185 and Y is quality version from A to E
I wanna select each image name with different quality.
The output should be
+-----+---------+------------------------+
| ID | ID_TEST | FILE_PATH |
+-----+---------+------------------------+
| 575 | 3 | Landscapes_001_h_A.jpg |
| 576 | 3 | Landscapes_002_h_E.jpg |
| 577 | 3 | Landscapes_003_h_C.jpg |
| 578 | 3 | Landscapes_004_h_B.jpg |
| 579 | 3 | Landscapes_005_h_D.jpg |
| 580 | 3 | Landscapes_006_h_A.jpg |
| 581 | 3 | Landscapes_007_h_E.jpg |
| 582 | 3 | Landscapes_008_h_C.jpg |
| 583 | 3 | Landscapes_009_h_B.jpg |
| 584 | 3 | Landscapes_010_h_E.jpg |
+-----+---------+------------------------+
but of course for 185 elements.
I'm using 5.5.60-MariaDB.
How to write SELECT statement? Using REGEXP?

SQL subcategory total is not properly placed at the end of every parent category

I am having trouble in SQl query,The query result should be like this
+------------+------------+-----+------+-------+--+--+--+
| District | Tehsil | yes | no | Total | | | |
+------------+------------+-----+------+-------+--+--+--+
| ABBOTTABAD | ABBOTTABAD | 377 | 5927 | 6304 | | | |
| ABBOTTABAD | HAVELIAN | 112 | 2276 | 2388 | | | |
| ABBOTTABAD | Overall | 489 | 8203 | 8692 | | | |
| CHARSADDA | CHARSADDA | 289 | 3762 | 4051 | | | |
| CHARSADDA | SHABQADAR | 121 | 1376 | 1497 | | | |
| CHARSADDA | TANGI | 94 | 1703 | 1797 | | | |
| CHARSADDA | Overall | 504 | 6841 | 7345 | | | |
+------------+------------+-----+------+-------+--+--+--+
The overall total should be should be shown at the end of every parent category but now it is showing like this
+------------+------------+-----+------+-------+--+--+--+
| District | Tehsil | yes | no | Total | | | |
+------------+------------+-----+------+-------+--+--+--+
| ABBOTTABAD | ABBOTTABAD | 377 | 5927 | 6304 | | | |
| ABBOTTABAD | HAVELIAN | 112 | 2276 | 2388 | | | |
| ABBOTTABAD | Overall | 489 | 8203 | 8692 | | | |
| CHARSADDA | CHARSADDA | 289 | 3762 | 4051 | | | |
| CHARSADDA | Overall | 504 | 6841 | 7345 | | | |
| CHARSADDA | SHABQADAR | 121 | 1376 | 1497 | | | |
| CHARSADDA | TANGI | 94 | 1703 | 1797 | | | |
+------------+------------+-----+------+-------+--+--+--+
My query is sorting second column with respect to first column although order by query is applied on my first column. This is my query
select District as 'District', tName as 'tehsil',[1] as 'yes',[0] as 'no',ISNULL([1]+[0], 0) as "Total" from
(
select d.Name as 'District',
case when grouping (t.Name)=1 then 'Overall' else t.Name end as tName,
BoundaryWallAvailable,
count(*) as total from School s
INNER JOIN SchoolIndicator i ON (i.refSchoolID=s.SchoolID)
INNER JOIN Tehsil t ON (t.TehsilID=s.refTehsilID)
INNER JOIN district d ON (d.DistrictID=t.refDistrictID)
group by
GROUPING sets((d.Name, BoundaryWallAvailable), (d.Name,t.Name, BoundaryWallAvailable))
) B
PIVOT
(
max(total) for BoundaryWallAvailable in ([1],[0])
) as Pvt
order by District
P.S: BoundaryWall is one column through pivoting i am breaking it into Yes and No Column

Excel VBA Matching against all cells in a specific column

This table is made by pulling a variable number of columns from several workbooks into one. I keep track of the column index for "Key1" and "Key2" with integers "i1" and "i2", respectively.
+-------------+-----------+-------------+-----------+-----------+--------+-------------+-----------+-------+
| Thisjust | Indexcode | Specialcode | Key1 | Indexcode | Some | Specialcode | Key2 | MATCH |
+-------------+-----------+-------------+-----------+-----------+--------+-------------+-----------+-------+
| isanexample | 101 | 27223 | 101_27223 | 101 | Values | 1112 | 101_1112 | |
| isanexample | 102 | 27224 | 102_27224 | 102 | Values | 1113 | 102_1113 | |
| isanexample | 103 | 27225 | 103_27225 | 103 | Values | 1114 | 103_1114 | |
| isanexample | 104 | 27226 | 104_27226 | 104 | Values | 1115 | 104_1115 | |
| isanexample | 108 | 11130 | 108_11130 | 105 | Values | 1116 | 105_1116 | Yes |
| isanexample | 106 | 27228 | 106_27228 | 106 | Values | 1117 | 106_1117 | |
| isanexample | 107 | 27229 | 107_27229 | 107 | Values | 1118 | 107_1118 | |
| isanexample | 110 | 27227 | 110_27227 | 108 | Values | 11130 | 108_11130 | Yes |
| isanexample | 109 | 37345 | 109_37345 | 109 | Values | 1112 | 109_1112 | |
| isanexample | 105 | 37346 | 105_37346 | 110 | Values | 1113 | 110_1113 | |
| isanexample | 111 | 37347 | 111_37347 | 111 | Values | 1114 | 111_1114 | |
| isanexample | 112 | 37348 | 112_37348 | 112 | Values | 1115 | 112_1115 | |
| isanexample | 113 | 37349 | 113_37349 | 113 | Values | 1116 | 113_1116 | |
| isanexample | 114 | 37350 | 114_37350 | 114 | Values | 1117 | 114_1117 | |
| isanexample | 115 | 37351 | 115_37351 | 115 | Values | 1118 | 115_1118 | |
| isanexample | 116 | 11138 | 116_11138 | 116 | Values | 11138 | 116_11138 | Yes |
| isanexample | 117 | 11139 | 117_11139 | 117 | Values | 11139 | 117_11139 | Yes |
| isanexample | 118 | 11140 | 118_11140 | 118 | Values | 11140 | 118_11140 | Yes |
+-------------+-----------+-------------+-----------+-----------+--------+-------------+-----------+-------+
I am checking if
EITHER key1 in a particular row matches one of the key2 cells
OR if key2 in a particular row matches one of the key1 cells
I used this formula to accomplish that
=IF(AND(ISNA(MATCH(H2,$D$2:$D$19,0)),ISNA(MATCH(D2,$H$2:$H$19,0))),"","Yes")
Knowing that this whole table could have a wildly different number of columns, and the order of columns is also variable:
How do I do my match function in VBA? The MATCH column will always be at the end.
If you are fine with creating a Table (ListObject) from your data, your MATCH column formula will be =IF(AND(ISNA(MATCH([Key1],[Key2],0)),ISNA(MATCH([Key2],[Key1],0))),"","Yes").
This references the Key1 and Key2 columns based on their headers, eliminating the problem of a changing number and/or order of columns.

SQL Group Results and Add them up based on product

I've got the following SQL which basically works out the costings etc for each item.
SELECT
L.LocID,
L.LocationName,
L.LocationSqrMtr,
L.LocationAddress,
L.LocationPostCode,
L.LocationContact,
I.SubPIDItemID,
I.SPID,
I.ProductID,
C.SubPIDCostID,
C.PricePerItem,
C.ManDayPerItem
FROM
dbo.SubPIDCosts AS C
INNER JOIN dbo.SubPIDItems AS I ON
C.ProductID = I.ProductID
RIGHT OUTER JOIN dbo.SubPIDLocations AS L ON
I.LocationID = L.LocID AND C.LocationID = L.LocID
WHERE C.SPID = 48
This returns:
+-------+--------------+----------------+-----------------+------------------+-----------------+--------------+----------+-----------+--------------+--------------+---------------+-----+----+---+-----+--------+--------+--------+------+
| LocID | LocationName | LocationSqrMtr | LocationAddress | LocationPostCode | LocationContact | SubPIDItemID | SPID | ProductID | SubPIDCostID | PricePerItem | ManDayPerItem | | | | | | | | |
+-------+--------------+----------------+-----------------+------------------+-----------------+--------------+----------+-----------+--------------+--------------+---------------+-----+----+---+-----+--------+--------+--------+------+
| 379 | | | Location | 1 | 1 | 345 | Generic | Building | Generic | Building | NULL | 158 | 48 | | | | 108 | 0.3400 | 6.17 |
| 379 | | | Location | 1 | 1 | 345 | Generic | Building | Generic | Building | NULL | 159 | 48 | 1 | 109 | 0.3400 | | .47 | |
| 379 | 3 | Location | 1 | 615 | Generic | Building | Generic | Building | NULL | 160 | 48 | | | | 110 | 0.7317 | 0.50 | | |
| 379 | 4 | Location | | | 615 | Generic | Building | Generic | Building | NULL | 161 | 48 | | | | 111 | 0.7317 | 0.50 | |
| 379 | 4 | Location | | | 615 | Generic | Building | Generic | Building | NULL | 16 | | 48 | 1 | 11 | | 0.7317 | 0.50 | |
+-------+--------------+----------------+-----------------+------------------+-----------------+--------------+----------+-----------+--------------+--------------+---------------+-----+----+---+-----+--------+--------+--------+------+
But what I would like to do is group it by the product ID. So all the ones that are ProductID 22 it should add the values up for ManDayPerItem and PricePerItem and LocationSqrMtr
It's used in the following context
I'd like to have them grouped nicely in that list.
As you said, group by:
SELECT ProductID, SUM(ManDayPerItem), SUM(PricePerItem), SUM(LocationSqrMtr)
FROM
dbo.SubPIDCosts AS C
INNER JOIN dbo.SubPIDItems AS I ON
C.ProductID = I.ProductID
RIGHT OUTER JOIN dbo.SubPIDLocations AS L ON
I.LocationID = L.LocID AND C.LocationID = L.LocID
WHERE C.SPID = 48
GROUP BY ProductID;