--- title: "First value in group" description: "Use idiomatic Materialize SQL to find the first value in each group." menu: main: parent: idiomatic-materialize-sql identifier: idiomatic-materialize-first-value weight: 10 --- ## Overview The "first value in each group" query pattern returns the first value, according to some ordering, in each group. {{< callout >}} ### Materialize and window functions {{< idiomatic-sql/materialize-window-functions >}} {{ callout >}} ## Idiomatic Materialize SQL **Idiomatic Materialize SQL:** To find the first value in each group, use [MIN()](/sql/functions/#min) or [MAX()](/sql/functions/#max) aggregate function in a subquery.
Use a subquery that uses the [MIN()](/sql/functions/#min) or
[MAX()](/sql/functions/#max) aggregate function.
```mzsql
SELECT tableA.fieldA, tableA.fieldB, minmax.Z
FROM tableA,
(SELECT fieldA,
MIN(fieldZ),
MAX(fieldZ)
FROM tableA
GROUP BY fieldA) minmax
WHERE tableA.fieldA = minmax.fieldA
ORDER BY fieldA ... ;
```
|
|
```nofmt
-- Anti-pattern. Avoid. --
SELECT fieldA, fieldB,
FIRST_VALUE(fieldZ) OVER (PARTITION BY fieldA ORDER BY ...),
FIRST_VALUE(fieldZ) OVER (PARTITION BY fieldA ORDER BY ... DESC)
FROM tableA
ORDER BY fieldA, ...;
```
|
```mzsql SELECT o.order_id, minmax.lowest_price, o.item, o.price, o.price - minmax.lowest_price AS diff_lowest_price FROM orders_view o, (SELECT order_id, MIN(price) AS lowest_price FROM orders_view GROUP BY order_id) minmax WHERE o.order_id = minmax.order_id ORDER BY o.order_id, o.item; ``` | |
```nofmt
-- Anti-pattern --
SELECT order_id,
FIRST_VALUE(price)
OVER (PARTITION BY order_id ORDER BY price) AS lowest_price,
item,
price,
price - FIRST_VALUE(price)
OVER (PARTITION BY order_id ORDER BY price) AS diff_lowest_price
FROM orders_view
ORDER BY order_id, item;
```
|
```mzsql SELECT o.order_id, minmax.highest_price, o.item, o.price, o.price - minmax.highest_price AS diff_highest_price FROM orders_view o, (SELECT order_id, MAX(price) AS highest_price FROM orders_view GROUP BY order_id) minmax WHERE o.order_id = minmax.order_id ORDER BY o.order_id, o.item; ``` | |
```nofmt
-- Anti-pattern --
SELECT order_id,
FIRST_VALUE(price)
OVER (PARTITION BY order_id ORDER BY price DESC) AS highest_price,
item,
price,
price - FIRST_VALUE(price)
OVER (PARTITION BY order_id ORDER BY price DESC) AS diff_highest_price
FROM orders_view
ORDER BY order_id, item;
```
|
```mzsql SELECT o.order_id, minmax.lowest_price, minmax.highest_price, o.item, o.price, o.price - minmax.lowest_price AS diff_lowest_price, o.price - minmax.highest_price AS diff_highest_price FROM orders_view o, (SELECT order_id, MIN(price) AS lowest_price, MAX(price) AS highest_price FROM orders_view GROUP BY order_id) minmax WHERE o.order_id = minmax.order_id ORDER BY o.order_id, o.item; ``` | |
```nofmt
-- Anti-pattern --
SELECT order_id,
FIRST_VALUE(price)
OVER (PARTITION BY order_id ORDER BY price) AS lowest_price,
FIRST_VALUE(price)
OVER (PARTITION BY order_id ORDER BY price DESC) AS highest_price,
item,
price,
price - FIRST_VALUE(price)
OVER (PARTITION BY order_id ORDER BY price) AS diff_lowest_price,
price - FIRST_VALUE(price)
OVER (PARTITION BY order_id ORDER BY price DESC) AS diff_highest_price
FROM orders_view
ORDER BY order_id, item;
```
|