How can I convert my columns into rows and vice versa - postgresql

I have a query wherein I have week, avg_pts, avg_fgm, avg_fga, pct, avg_fg3m as columns. Is there a way wherein I could make weeks 1 to 7 into a column? And the current columns into rows?
Expected Output:
Stats Week1 Week2 Week3 Week4 Week5 Week6 Week7
Avg_pts 113.00 ... ... .. ..
avg_fgm 42.00 .... ... ...
avg_fga 88.00 .... ... ...
pct 0.51 .. .... ....
avg_fg3m 11.00 .... ... ....

Related

Postgres subquery with a separate aggregate?

I have a feeling that the answer here is something to do with pivot tables... however, this is what I am struggling to do. The source table has many report ids and more landcover and data types but I think this illustrates things...
here is part of the table I am querying.
report_id
landcover_type
data_type
mean
area
615
Acid grassland
canopyheight
2
493.9125
615
Arable and horticulture
canopyheight
4
0.86
615
Acid grassland
carbonstoragewoodlands
8
493.9125
615
Arable and horticulture
carbonstoragewoodlands
16
0.86
Is there a simple way to query the data and get the following...
report_id
landcover_type
mean_canopy_height
mean_carbonstorage
615
Acid grassland
2
8
615
Arable and horticulture
4
16
I am not sure the following gives you what you want, but it does give you what you asked for. All that it requires is simple MIN/MAX values of the mean column.
with dataset(report_id, landcover_type, data_type, mean, area) as
( values ( 615, 'Acid grassland', 'canopyheight', 2, 493.9125 )
, ( 615, 'Arable and horticulture', 'canopyheight', 4, 0.86 )
, ( 615, 'Acid grassland', 'carbonstoragewoodlands', 8, 493.9125 )
, ( 615, 'Arable and horticulture', 'carbonstoragewoodlands', 16, 0.86)
)
select report_id
, landcover_type
, min(mean) mean_canopy_height
, max(mean) mean_carbonstorage
from dataset
group by report_id, landcover_type
order by landcover_type;
If not what you actually want, then you need to clarify what you want and/or modify the expected results given the same imput.

CASE where a lot of text needs trimming

I have an output in my queries that gives me:
xxxxxxx xxxxxxxxx : 123456 (xx) - xxxxxxx...
or
xxxxxxx xxxxxxxxx : 12345678 (xx) - xxxxxxx...
basically text before either a 6 or 8 digit number then text after.
Ideally I'd like to be able to CASE this column so I'd have an output where it's a 6 digit number = London and the output when it's an 8 digit number = Paris.
But I am very stuck on how to get the CASE statement to achieve this - essentially trim out a lot of text, work out if the number is either 6 or 8 digits long, then tell me if it's London or Paris. I'm not sure if it's possible.
Is this sort of CASE statement achievable? Advise / pointers would be very gratefully received. Thanks very much.
One way to do it is using a common table expression with patindex.
First, create and populate sample table (Please save us this step in your future questions)
DECLARE #T As Table
(
LongText varchar(4000)
)
INSERT INTO #T (LongText) VALUES
('.njauaerigha n uaer gauer 345 gnaehn 123456 (43) smgmshmsrtmh s;s nt;srtn ;nbtugarg '),
('asdfasdfasdf 12345678 (65) asdfag gr 34 6sd 64 fasd fasdfas d fasdfasdf asdf'),
('zxcvzxcvzx34cv zxcvzxcv zxcv zxcv zxcv zcxvz xcv z3 45 xcvzxcz dfg dv df df zfd zdf b 654321 (77)'),
('87654321 (99) n;arng an ; ualerg trhrt srth str sth strh ssth'),
('snhs tgnn ang nu g;arug aegaerlhae s ;5 afnauierhga.ngae489tj 8q3y .sn.5yn b.s n .5hy 5');
Then, the common table expression to get the start index of the 8/6 digit number:
WITH CTE AS
(
SELECT LongText,
PATINDEX('%[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9] ([0-9][0-9])%', LongText) As Long,
PATINDEX('%[0-9][0-9][0-9][0-9][0-9][0-9] ([0-9][0-9])%', LongText) As Short
FROM #T
)
Then, select with a couple of case expressions to extract the number and get the city:
SELECT CASE
WHEN Long > 0 THEN SUBSTRING(LongText, Long, 13)
WHEN Short > 0 THEN SUBSTRING(LongText, Short, 11)
END As Number,
CASE
WHEN Long > 0 THEN 'Paris'
WHEN Short > 0 THEN 'London'
END As City,
LongText
FROM CTE
Results:
Number City LongText
123456 (43) London .njauaerigha n uaer gauer 345 gnaehn 123456 (43) smgmshmsrtmh s;s nt;srtn ;nbtugarg
12345678 (65) Paris asdfasdfasdf 12345678 (65) asdfag gr 34 6sd 64 fasd fasdfas d fasdfasdf asdf
654321 (77) London zxcvzxcvzx34cv zxcvzxcv zxcv zxcv zxcv zcxvz xcv z3 45 xcvzxcz dfg dv df df zfd zdf b 654321 (77)
87654321 (99) Paris 87654321 (99) n;arng an ; ualerg trhrt srth str sth strh ssth
NULL NULL snhs tgnn ang nu g;arug aegaerlhae s ;5 afnauierhga.ngae489tj 8q3y .sn.5yn b.s n .5hy 5

SQL Server 2012 finding text before and after delimiter and sometimes without delimiter

I have been having fun with an issue where I need to break apart a string in SQL Server 2012 and test for values it may or may not contain. The values, when present, will be separated by up to two different ; symbols.
When there is nothing, it will be blank.
When there is a single value, it will show up without the delimiter.
When there are two or more, up to 3, they will be separated by the delimiter.
As I said, if there is nothing in the record, it will be blank. Below are some example of how the data may come across:
' ',
'1',
'24',
'15;1;24',
'10;1;22',
'5;1;7',
'12;1',
'10;12',
'1;5',
'1;1;1',
'15;20;22'
I have searched the forums and found many clues, but I have not been able to come up with a total solution given all potential data values. Essentially, I would like to break it into 3 separate values.
text before the first delimiter or in the absence of the delimiter, just the text.
Text after the first delimiter and before the second in situation where there are two delimiters.
The following has worked consistently:
substring(SUBSTRING(Food_Desc, charindex(';', Food_Desc) + 1, 4), 0,
charindex(';', SUBSTRING(Food_Desc, charindex(';', Food_Desc) + 1, 4))) as [Middle]
Text after the second delimiter in the even there are two delimiters and there is a third value
The main challenge is the fact that the delimiter, when present, moves depending on the value in the table. values 1-9 make it show up as the second character in the string, values 10-24 make it show up as the 3rd, etc.
Any help would be greatly appreciated.
This is simple if you have a well written t-sql splitter function. For this solution I'm using Jeff Moden's delimitedsplit8k.
sample data and solution
DECLARE #table table (someid int identity, sometext varchar(100));
INSERT #table VALUES (' '),('1'),('24'),('15;1;24'),('10;1;22'),
('5;1;7'),('12;1'),('10;12'),('1;5'),('1;1;1'),('15;20;22');
SELECT
someid,
sometext,
ItemNumber,
Item
FROM #table
CROSS APPLY dbo.DelimitedSplit8K_LEAD(sometext, ';');
results
someid sometext ItemNumber Item
----------- ----------------- ----------- --------
1 1
2 1 1 1
3 24 1 24
4 15;1;24 1 15
4 15;1;24 2 1
4 15;1;24 3 24
5 10;1;22 1 10
5 10;1;22 2 1
5 10;1;22 3 22
6 5;1;7 1 5
6 5;1;7 2 1
6 5;1;7 3 7
7 12;1 1 12
7 12;1 2 1
8 10;12 1 10
8 10;12 2 12
9 1;5 1 1
9 1;5 2 5
10 1;1;1 1 1
10 1;1;1 2 1
10 1;1;1 3 1
11 15;20;22 1 15
11 15;20;22 2 20
11 15;20;22 3 22
Below is a modified version of a similar question How do I split a string so I can access item x?. Changing the text value for #sample to each of your possibilities listed seemed to work for me.
DECLARE #sample VARCHAR(200) = '15;20;22';
DECLARE #individual VARCHAR(20) = NULL;
WHILE LEN(#sample) > 0
BEGIN
IF PATINDEX('%;%', #sample) > 0
BEGIN
SET #individual = SUBSTRING(#sample, 0, PATINDEX('%;%', #sample));
SELECT #individual;
SET #sample = SUBSTRING(#sample, LEN(#individual + ';') + 1, LEN(#sample));
END;
ELSE
BEGIN
SET #individual = #sample;
SET #sample = NULL;
SELECT #individual;
END;
END;

Merging lines in a view into a new view

I have a view with 7 columns. 4 columns contain the same information, two of three other columns contain NULL when one column (out of these three) contain something (NOT NULL). The columns "Gewicht, aantal, klant" have to be merged into one line with the four first columns containing the information that is the same in all three lines.
How can i create a view with these lines merged into 1 line?
now view looks like:
>
Produtielijn Datum_tijd Artikel PRorder Gewicht aantal klant
Afzaklijn 3 (Groot Loosbroek) 2017-01-16 15:55:04.000 0118903G34 PR0800055654.006 NULL NULL 30041 NE06-07 Garretsen
Afzaklijn 3 (Groot Loosbroek) 2017-01-16 15:55:04.000 0118903G34 PR0800055654.006 NULL 205 NULL
Afzaklijn 7 (BB Veghel) 2017-01-02 16:40:32.000 0125995AA11 PR0800055388 NULL NULL 31488 NE49-69 Mohle(Jarco)
Afzaklijn 7 (BB Veghel) 2017-01-02 16:40:32.000 0125995AA11 PR0800055388 2600 NULL NULL
Afzaklijn 7 (BB Veghel) 2017-01-02 16:40:32.000 0125995AA11 PR0800055388 NULL 4 NULL
I want the view to look like:
Produtielijn Datum_tijd Artikel PRorder Gewicht aantal klant
Afzaklijn 3 (Groot Loosbroek) 2017-01-16 15:55:04.000 0118903G34 PR0800055654.006 NULL 205 30041 NE06-07 Garretsen
Afzaklijn 7 (BB Veghel) 2017-01-02 16:40:32.000 0125995AA11 PR0800055388 2600 4 31488 NE49-69 Mohle(Jarco)
First and foremost you want to sort your data out.
Secondly, assuming you have one row per value in each of your Gewicht, aantal and klant columns with the 'non-values' always being NULL you can just use max and group by:
select Produtielijn
,Datum_tijd
,Artikel
,PRorder
,max(Gewicht) as Gewicht
,max(aantal) as aantal
,max(klant) as klant
from View
group by Produtielijn
,Datum_tijd
,Artikel
,PRorder

Pulling correct results from my PitchValues Table

I am getting a tad frustrated and was wondering if you can help:
I have a Pitch Values Table with the following Columns PitchValues_Skey, PitchType_Skey (this is a foreign key), Start Date, End Date and finally value:
For Example:
1 7 01/01/2010 31/12/2010 £15
2 7 01/01/2011 31/12/2011 £20
And all I want to do is update my Bookings table with how much each booking is going to be, so I put together the code below which worked fine when I only had 2010 data, but I know have 2011 and 2012 and want to update it but it will only update with the 2010 prices.
SELECT Bookings.Booking_Skey, DATEDIFF(day, Bookings.ArrivalDate, Bookings.DepartureDate) * PitchValues.Value AS BookingValue,
PitchValues.PitchType_Skey
FROM Bookings INNER JOIN
PitchValues ON Bookings.PitchType_Skey = PitchValues.PitchType_Skey
WHERE (Bookings.Booking_Skey = 1)
So when I run the query above I would expect to see one line of data but instead I see 4 (See Below)
I would expect this:
Booking_Skey BookingValue PitchType_Skey
1 420 4
But I get this
Booking_Skey BookingValue PitchType_Skey
1 420 4
1 453.6 4
1 476.7 4
1 476.7 4
All sorted now, thanks for your help.
SELECT Bookings.Booking_Skey, DATEDIFF(DAY, Bookings.ArrivalDate, Bookings.DepartureDate) * PitchValues.Value AS BookingValue, PitchValues.PitchType_Skey
FROM Bookings
INNER JOIN PitchValues ON Bookings.PitchType_Skey = PitchValues.PitchType_Skey
AND Bookings.ArrivalDate BETWEEN PitchValues.StartDate AND PitchValues.EndDate
WHERE (Bookings.Booking_Skey = 1)