TSQL transpose rows to columns based on fixed set of input values - tsql

I want to transpose a table based on a limited number of input values for column Brand
My source:
Id
Brand
Type
1
Adidas
Type A
1
Puma
Type B
2
Adidas
Type C
2
Puma
Type D
Desired Output:
Id
Brand Adidas
Type Adidas
Brand Puma
Type Puma
1
Adidas
Type A
Puma
Type B
2
Adidas
Type C
Puma
Type D
I am pretty sure this can be done using the Pivot function but i have no clue how.

Hm. Found out by myself without using a PIVOT function.
SELECT
Id,
MAX(CASE WHEN Brand = 'Adidas' THEN [Brand] END) AS [Brand Adidas],
MAX(CASE WHEN Brand = 'Adidas' THEN [Type] END) AS [Type Adidas],
MAX(CASE WHEN Brand = 'Puma' THEN [Series] END) AS [Brand Puma],
MAX(CASE WHEN Brand = 'Puma' THEN [Type] END) AS [Type Puma]
FROM MyTable
GROUP BY Id
Output:
Id
Brand Adidas
Type Adidas
Brand Puma
Type Puma
1
Adidas
Type A
Puma
Type B
2
Adidas
Type C
Puma
Type D

Related

How to multiple decimal numbers in column within a group by?

I have sql table that looks like this:
date id value type
2020-01-01 1 1.03 a
2020-01-01 1 1.02 a
2020-01-02 2 1.06 a
2020-01-02 2 1.2 a
2020-01-03 3 1.09 b
I need to build a query that groups by date,id, and type by multiplying the value column whereever type = 'a'.
what new table should look like:
date id value type
2020-01-01 1 1.0506 a
2020-01-02 2 1.272 a
2020-01-03 3 1.09 b
currently I am building this query,
select
date, id, value, type
from my_table
where date between 'some date' and 'some date'
and trying to fit in EXP(SUM(LOG(value)
but, how do I do the multiplication only where type = 'a' in a group by?
edit:
there are more than 2 values in the type column
I am using redshift. Not postgresql.
select date
, id
-- use the 'case' syntax to check if it is type 'a'
, case when type = 'a' then EXP(SUM(LOG(value::float))) -- your multiply logic
else max(value) -- use min or max to pick only one value
end as value
from my_table
where date between 'some date' and 'some date'
group
by date, id, type

Group by and sum depending on cases in Google Big Query

The data looks like-
A_value B_value C_value Type
1 null null A
2 null null A
null 3 null B
null 4 null B
null null 5 C
null null 6 C
When Type is 'A' I want to sum the 'A_value' and store in a different column called 'Type_value', when Type is 'B' I want to sum the 'B_value' and store in the column 'Type_value' and do similar for 'C'
Expected results-
Type_value Type
3 A
7 B
11 C
How to achieve this result?
Below is for BigQuery Standard SQL
#standardSQL
SELECT SUM(CASE Type
WHEN 'A' THEN A_value
WHEN 'B' THEN B_value
WHEN 'C' THEN C_value
ELSE 0
END) AS Type_value, Type
FROM `project.dataset.table`
GROUP BY Type
If to apply to sample data in your question - result is
Row Type_value Type
1 3 A
2 7 B
3 11 C
Another potential option is to reuse the fact that your data has pattern of having value only in respective columns. So if it is true - you can use below version
#standardSQL
SELECT SUM(IFNULL(A_value, 0) + IFNULL(B_value, 0) + IFNULL(C_value, 0)) AS Type_value, Type
FROM `project.dataset.table`
GROUP BY Type
with same result obviously

Postgres - bind results of equal type by year - long to wide data

Please excuse my not very propper way of asking this as i am new to postgres...
Having the following two tables:
CREATE TABLE pub (
id int
, time timestamp
);
id time
1 1 2010-02-10 01:00:00
2 2 2011-02-10 01:00:00
3 3 2012-02-10 01:00:00
And
CREATE TABLE val (
id int
, type text
, val int
);
id type val
1 1 A 1
2 1 B 2
3 1 C 3
4 2 A 4
5 2 B 5
6 3 D 6
I would like to get the following output (for id <= 2 )
type 2010 2011
1 A 1 4
2 B 2 5
3 C 3 NULL
So type is the superset of all type's present in table val.
NULL meaning that there is no value for label C.
Ideally the column-headings are are years of the time. Alternatively the id itself...
Exists at least two ways to do this.
If your table have not many categories you can use CTE
WITH x AS (
SELECT type,
sum(val) FILTER (WHERE date_part('year', time) = 2010) AS "2010",
sum(val) FILTER (WHERE date_part('year', time) = 2011) AS "2011"
FROM pub AS p JOIN val AS v ON (v.id = p.id)
GROUP BY type
)
SELECT * FROM x
WHERE "2010" is NOT NULL OR "2011" IS NOT NULL
ORDER BY type
;
But if you have many or dynamic categories you must use crosstab:
CREATE EXTENSION tablefunc;
SELECT * FROM crosstab(
$$
SELECT type,
date_part('year', time)::text as time,
sum(val) AS val
FROM pub AS p JOIN val AS v ON (v.id = p.id)
GROUP BY type, 2
ORDER BY 1, 2
$$,
$$VALUES ('2010'::text), ('2011'), ('2012') $$
) AS ct (type text, "2010" int, "2011" int, "2012" int);
;

Tableau: A bar which shows the difference between

I have the following data for which i need to create a bar chart as shown in the picture in tableau:
Brand Sales week
A 12 1
B 20 1
C 14 1
A 12 2
B 22 2
C 16 2
A 18 3
B 16 3
C 27 3
My chart must contain sales in rows and week in columns. For every week, I must show three bars:
Sales for Brand A (A is always fixed)
sales for Brand B/ Brand C (B/C:- Its a parameter selection)
Difference between sales of these two
Is this what you asking for ??
You can do this by creating calculated fields of the sales for Brand A, Brand B/C (based on selection), and the difference between those two calculated fields:
Brand A Sales: SUM(IF [Brand] = 'A' THEN [Sales] END)
Brand B/C Sales: SUM(IF [Brand] != 'A' THEN [Sales] END)
Brand Difference: [Brand A Sales] - [Brand B/C Sales]
The calculation is dependent on your filter being setup properly, so make sure you have something like this calculated field in your filter card and set to True:
Brand Filter: [Brand Select] = [Brand] OR [Brand] = 'A' [Brand Select] is the parameter to select between B or C
Lastly, place [Measure Names] in the columns section and [Measure Values] in the rows section. Be sure only to include the 3 calculated fields mentioned above.
You should get a result like so:
Brand B -
Brand C -
Note: The calculation for the difference between brands may need to be altered based on your expected output. I based mine in the example off of what I assumed you had within the image in your post.

Select all Items which don't have a particular value in another table

Table: Car
Columns: CarID, Value
Table: Tyres
Columns: TyreID, CarID, Brand
How can I select all Cars which don't have a corresponding Tyre which is of a certain Brand. In this scenario a car could have a number of different tyres each of which has a different brand.
E.g.
Car1 has 4 tyres, 2 x Brand A, 1 x Brand B, 1 x Brand C.
Car2 has 3 tyres, 1 x Brand A, 2 x Brand B.
Car3 has 4 tyres, 3 x Brand A, 1 x Brand C.
I want to find out the CarID of all vehicles which don't have a single tyre of Brand C. In this instance the result would be Car2.
Example Data:
Car
CarID Value
--------------
1 Abc
2 Def
3 Geh
Tyre
TyreID CarID Brand
----------------
1 1 Brand A
2 1 Brand A
3 1 Brand B
4 1 Brand C
5 2 Brand A
6 2 Brand B
7 2 Brand B
8 3 Brand A
9 3 Brand A
10 3 Brand A
11 3 Brand C
Result
ID 2
Use NOT EXISTS instead NOT IN because IN clause have a limit of 2500 rows
SELECT CarID
FROM Car
WHERE NOT EXISTS (
SELECT 'X'
FROM Tyres
WHERE Brand='Brand C'
and Tyres.carId = Car.carId
)
You can use NOT IN clause
SELECT CarID
FROM Car
WHERE CarID NOT IN (
SELECT CarID
FROM Tyres
WHERE Brand='Brand C'
)