2

I am trying to incorporate the null values within the returned lists, such that:

batch_id   |test_name   |test_value
-----------------------------------
10         | pH         | 4.7
10         | Temp       | 154
11         | pH         | 4.8
11         | Temp       | 152
12         | pH         | 4.5
13         | Temp       | 155
14         | pH         | 4.9
14         | Temp       | 152
15         | Temp       | 149
16         | pH         | 4.7
16         | Temp       | 150

would return:

batch_id   | pH         |Temp 
---------------------------------------
10         |  4.7       |   154
11         |  4.8       |   152
12         |  4.5       |   <null>
13         |  <null>    |   155
14         |  4.9       |   152
15         |  <null>    |   149
16         |  4.7       |   150

However, it currently returns this:

batch_id   | pH         |Temp 
---------------------------------------
10         |  4.7       |   154
11         |  4.8       |   152
12         |  4.5       |   <null>
13         |  155       |   <null>
14         |  4.9       |   152
15         |  149       |   <null>
16         |  4.7       |   150

This is an extension of a prior question - Can the categories in the postgres tablefunc crosstab() function be integers? - which led to this current query:

SELECT *
 FROM crosstab('SELECT lab_tests_results.batch_id, lab_tests.test_name, lab_tests_results.test_result::FLOAT
                FROM lab_tests_results, lab_tests
                WHERE lab_tests.id=lab_tests_results.lab_test AND (lab_tests.test_name LIKE ''Test Name 1'' OR lab_tests.test_name LIKE ''Test Name 2'')
                ORDER BY 1,2'
            )   AS final_result(batch_id VARCHAR, test_name_1 FLOAT, test_name_2 FLOAT);

I also know that I am not the first to ask this question generally, but I have yet to find a solution that works for these circumstances. For example, this one - How to include null values in `tablefunc` query in postgresql? - assumes the same Batch IDs each time. I do not want to specify the Batch IDs, but rather all that are available.

This leads into the other set of solutions I've found out there, which address a null list result from specified categories. Since I'm just taking what's already there, however, this isn't an issue. It's the null individual values causing the problem and resulting in a pivot table with values shifted to the left.

Any suggestions are much appreciated!

Edit: With Klin's help, got it sorted out. Something to note is that the VALUES section must match the actual lab_tests.test_name values you're after, such that:

SELECT *
    FROM crosstab(
            $$
                SELECT lab_tests_results.batch_id, lab_tests.test_name,  lab_tests_results.test_result::FLOAT
            FROM lab_tests_results, lab_tests
            WHERE lab_tests.id = lab_tests_results.lab_test
                AND (
                lab_tests_results.lab_test = 1 
                OR lab_tests_results.lab_test = 2 
                OR lab_tests_results.lab_test = 3 
                OR lab_tests_results.lab_test = 4 
                OR lab_tests_results.lab_test = 5 
                OR lab_tests_results.lab_test = 50 )
            ORDER BY 1 DESC, 2
        $$,
        $$
                VALUES('Mash pH'),
                    ('Sparge pH'),
                    ('Final Lauter pH'),
                    ('Wort pH'),
                    ('Wort FAN'),
                    ('Original Gravity'),
                    ('Mash Temperature')
        $$
        )   AS final_result(batch_id VARCHAR,
                            ph_mash FLOAT, 
                            ph_sparge FLOAT, 
                            ph_final_lauter FLOAT, 
                            ph_wort FLOAT, 
                            FAN_wort FLOAT, 
                            original_gravity FLOAT, 
                            mash_temperature FLOAT)

Thanks for the help!

1 Answer 1

2

Use the second form of the function:

crosstab(text source_sql, text category_sql) - Produces a “pivot table” with the value columns specified by a second query.

E.g.:

SELECT *
FROM crosstab(
    $$
        SELECT lab_tests_results.batch_id, lab_tests.test_name, lab_tests_results.test_result::FLOAT
        FROM lab_tests_results, lab_tests
        WHERE lab_tests.id=lab_tests_results.lab_test 
        AND (
            lab_tests.test_name LIKE 'Test Name 1' 
            OR lab_tests.test_name LIKE 'Test Name 2')
        ORDER BY 1,2
    $$,
    $$ 
        VALUES('pH'), ('Temp') 
    $$
) AS final_result(batch_id VARCHAR, "pH" FLOAT, "Temp" FLOAT);
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.