Flatten Postgers left join query result with dynamic values into one row - postgresql

I have two tables products and product_attributs. One Product can have one or many attributs and these are filled by a dynamic web form (name and value inputs) added by the user as needed. For example for a drill the user could decide to add two attributs : color=blue and power=100 watts. For another product it could be 3 or more different attribus and for another it could have no special attributs.
products
| id | name | identifier | identifier_type | active
| ----------|--------------|-------------|------------------|---
| 1 | Drill | AD44 | barcode | true
| 2 | Polisher | AP211C | barcode | true
| 3 | Jackhammer | AJ2133 | barcode | false
| 4 | Screwdriver | AS4778 | RFID | true
product_attributs
|id | name | value | product_id
|----------|--------------|-------------|----------
|1 | color | blue | 1
|2 | power | 100 watts | 1
|3 | size | 40 cm | 2
|4 | energy | electrical | 3
|4 | price | 35€ | 3
so attributs could be anything which are set dynamically by the user. My need is to generate a report on CSV which contain all products with their attributs. Without a good experience in SQL I generated the following basic request :
SELECT pr.name, pr.identifier_type, pr.identifier, pr.active, att.name, att.value
FROM products as pr
LEFT JOIN product_attributs att ON pr.id = att.product_id
as you know the result will contain for the same product as many rows as attributs it has and this is not ideal for reporting. The ideal would be this :
|name | identifier_type | identifier | active | name | value | name | value
|-----------|-----------------|------------|--------|--------|-------|------ |------
|Drill | barcode | AD44 | true | color | blue | power | 100 w
|Polisher | barcode | AP211C | true | size | 40 cm | null | null
|Jackhammer | barcode | AJ2133 | true | energy | elect | price | 35 €
|Screwdriver| barcode | AS4778 | true | null | null | null | null
here I only showed a max of two attributes per product but it could be more if needed. Well I did some research and came across the pivot with crosstab function on Postgres but the problem it requests static values but this does not match my need.
thanks lot for your help and sorry for duplicates if any.

Thanks Laurenz Albe for your help. array_agg solved my problem. Here is the query if someone may be interested in :
SELECT
pr.name, pr.description, pr.identifier_type, pr.identifier,
pr.internal_identifier, pr.active,
ARRAY_TO_STRING(ARRAY_AGG (oa.name || ' = ' || oa.value),', ') attributs
FROM
products pr
LEFT JOIN product_attributs oa ON pr.id = oa.product_id
GROUP BY
pr.name, pr.description, pr.identifier_type, pr.identifier,
pr.internal_identifier, pr.active
ORDER BY
pr.name;

Related

Insert a record for evey row from one table into another using one field in postesql

I'm trying to fill a table with data to test a system.
I have two tables
User
+----+----------+
| id | name |
+----+----------+
| 1 | Majikaja |
| 2 | User 2 |
| 3 | Markus |
+----+----------+
Goal
+----+----------+---------+
| id | goal | user_id |
+----+----------+---------+
I want to insert into goal one record for every user only using their IDs (they have to exists) and some fixed or random value.
I was thinking in something like this:
INSERT INTO Goal (goal, user_id) values ('Fixed value', select u.id from user u)
So it will generate:
Goal
+----+-------------+---------+
| id | goal | user_id |
+----+-------------+---------+
| 1 | Fixed value | 1 |
| 2 | Fixed value | 2 |
| 3 | Fixed value | 3 |
+----+-------------+---------+
I could just write a simple PHP script to achieve it but I wonder if is it possible to do using raw SQL only.

How to derive a column based on two different merged dimensions in SAP Business Objects?

I have two tables, and I want to derive one column from Table1 to Table2 by common fields Name and Color (by merging).
But until I was using only one merged dimension and it was working well for me.
Now, for two dimensions, it is not working.
If I have two tables :
Table1 Name : Fruits
|--------|--------|---------------|
| Name | Color | Rateperunit |
|--------|--------|---------------|
| banana | yellow | 3 |
|--------|--------|---------------|
| apple | red | 25 |
|--------|--------|---------------|
| apple | green | 30 |
|--------|--------|---------------|
Table2 Name : Purchase
|--------|---------|-------------|-----------|----------|
| Item | Color | Rateperunit | Noofitems | Totalbill|
|--------|---------|-------------|-----------|----------|
| apple | green |30 | 3 | 90 |
|--------|---------|-------------|-----------|----------|

PostgreSQL - How to do a Loop on a column

I am struggling to do a loop on a Postgres, but functions on postgres are not my piece of cake.
I have the following table on postgres:
| portfolio_1 | total_risk |
|----------------|------------|
| Top 10 Bets | |
| AAPL34 | 2,06699 |
| DISB34 | 1,712684 |
| PETR4 | 0,753324 |
| PETR3 | 0,087767 |
| VALE3 | 0,086346 |
| LREN3 | 0,055108 |
| AMZO34 | 0,0 |
| Bottom 10 Bets | |
| AAPL34 | 0,0 |
What I'm trying to do is get the values after the "Top 10 Bets" and before the "Botton 10 Bets".
My goal is the following result:
| portfolio_1 | total_risk |
|-------------|------------|
| AAPL34 | 2,06699 |
| DISB34 | 1,712684 |
| PETR4 | 0,753324 |
| PETR3 | 0,087767 |
| VALE3 | 0,086346 |
| LREN3 | 0,055108 |
| AMZO34 | 0,0 |
So, my goal is to take off the "Top 10 Bets", the "Botton 10 Bets" and the AAPL34 after the "Botton 10 Bets", which was repeated.
The quantity of rows is variable (I'm importing it from an Excel file), so I need a loop to do this, right?
SQL tables and result sets represent unordered sets. There is no "before" or "after" unless rows explicitly provide that information.
Let me assume that you have such a column, which I will call id for convenience.
Then you can do this in several ways. Here is one:
select t.*
from t
where t.id > (select min(t2.id) from t t2 where t2.portfolio_1 = 'Top 10 Bets') and
t.id < (select max(t2.id) from t t2 where t2.portfolio_1 = 'Bottom 10 Bets');

Using HiveQL, how do I pull the row with the highest integer?

I have a table with a few million rows of data that looks like this:
+---------------+--------------+-------------------+
| page | search_term | interactions |
+---------------+--------------+-------------------+
| /mom | pizza | 15 |
| /dad | pizza | 8 |
| /uncle | pizza | 2 |
| /brother | pizza | 7 |
| /mom | pasta | 12 |
| /dad | pasta | 23 |
+---------------+--------------+-------------------+
My goal is to run a HiveQL Query that will return the largest 'interactions' number for each unique page/term combo. For example:
+---------------+--------------+-------------------+
| page | search_term | interactions |
+---------------+--------------+-------------------+
| /dad | pasta | 23 |
| /mom | pizza | 15 |
+---------------+--------------+-------------------+
How would I write this considering that each unique page has hundreds of thousands of search_terms, but I only want to pull the one search_term with the most interactions?
I have tried using max(interactions) and max(struct(interactions, search_term)).col1 but have had no luck. My output is consistently giving me all of the search_terms for each page no matter how many interactions.
Thanks!
Use row_number() analytic function:
select page, search_term, interactions
from
(select page, search_term, interactions,
row_number() over (partition by page order by interactions desc ) rn
)s
where rn = 1;

Tableau to create single chart from multiple parameters

I have tableau workbook online
Before, I had filter for single Principal, and applied to all CUSIPs, and I was able to plot all the inflation-adjusted principals based on Index ratios for a particular date, (refer tab Inflation-Adjusted Trend) i.e.
Now, I have multiple filters based on multiple Principals, i.e. buy one CUSIP for $1500, buy another for $900, etc (refer tab Infl-Adjusted Trend 2)
These were the columns and rows
But I do not like the format of this graph.
I wish to have all the lines together in one graph, just like the single-principal tab below ..... how to fix this? How to bring all the values into one chart?
You currently have six calculated fields calculating your inflation-adjusted principals, one for each CUSIP. Here's what that table might end up looking like:
+-----------+-------------+-------------+-------------+-------------+-----+
| CUSIP | 912828H45 P | 912828NM8 P | 912828PP9 P | 912828QV5 P | ... |
+-----------+-------------+-------------+-------------+-------------+-----+
| 912828H45 | $100 | NULL | NULL | NULL | ... |
| 912828NM8 | NULL | $455 | NULL | NULL | ... |
| 912828PP9 | NULL | NULL | $132 | NULL | ... |
| 912828QV5 | NULL | NULL | NULL | $553 | ... |
| ... | ... | ... | ... | ... | ... |
+-----------+-------------+-------------+-------------+-------------+-----|
There's definitely a better way. Your fields are set up like this:
IF [Cusip] = "912828H45"
THEN
[912828H45 Principal] * [Index Ratio]
END
Instead of setting up one field per CUSIP, make a single field that calculates that value for each CUSIP.
IF [Cusip] = "912828H45"
THEN
[912828H45 Principal] * [Index Ratio]
ELSEIF [Cusip] = "912828NM8"
THEN
[912828NM8 Principal] * [Index Ratio]
...
END
Now your table looks like this.
+-----------+------------------------------+-----+
| CUSIP | Inflation-Adjusted Principal | ... |
+-----------+------------------------------+-----+
| 912828H45 | $100 | ... |
| 912828NM8 | $455 | ... |
| 912828PP9 | $132 | ... |
| 912828QV5 | $553 | ... |
| ... | ... | ... |
+-----------+------------------------------+-----+
That's a LOT easier to work with. Drag that single field into Rows and color by [Cusip].