Received: from malur.postgresql.org ([217.196.149.56]) by arkaria.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.94.2) (envelope-from ) id 1spsoo-005Anm-8I for pgsql-general@arkaria.postgresql.org; Sun, 15 Sep 2024 17:13:51 +0000 Received: from localhost ([127.0.0.1] helo=malur.postgresql.org) by malur.postgresql.org with esmtp (Exim 4.94.2) (envelope-from ) id 1spsom-0039tA-OS for pgsql-general@arkaria.postgresql.org; Sun, 15 Sep 2024 17:13:48 +0000 Received: from magus.postgresql.org ([2a02:c0:301:0:ffff::29]) by malur.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.94.2) (envelope-from ) id 1spsom-0039t1-Cg for pgsql-general@lists.postgresql.org; Sun, 15 Sep 2024 17:13:48 +0000 Received: from mail-lj1-f176.google.com ([209.85.208.176]) by magus.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 (Exim 4.94.2) (envelope-from ) id 1spsoi-001LIo-5s for pgsql-general@lists.postgresql.org; Sun, 15 Sep 2024 17:13:47 +0000 Received: by mail-lj1-f176.google.com with SMTP id 38308e7fff4ca-2f75428b9f8so29091901fa.3 for ; Sun, 15 Sep 2024 10:13:45 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1726420424; x=1727025224; h=content-transfer-encoding:cc:to:subject:message-id:date:from :in-reply-to:references:mime-version:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=Rwhf7EkI8gqlT4ulu9VG/cp4Bh7JGaevDGjnrrhsI5o=; b=MMESuD+bQg+ss5kdMmYrXBA5nDMajSUpotKJMamI9FtGMnWF1583gPwUauKw5PoTV+ 36UtYTNgKNVaESSsXiNDWZVmI5xOCcgtPlvbt4fmQ5N1xaLiN3Uz50lLNK1f3rfIhhfJ lT3ba3KoIeEAj2N5q5wzbxjpXqd/PYfpQ6x71KQE7+AKm7vlHSSWSPcmEEjCRQnUntkv rc/RheLTo3PJri551GaCgeHUpb6Ad8qWZ1a1LQWmhkvfqjrYRpAbaow7tbfBpTXr6hH0 14OBy5iXZNBDDFD6VMKBHUOQ/DPzbCZCPU7YyhBRIfKDXs2BcQ4sgDK1j7Pmqc95ISZW b7/w== X-Forwarded-Encrypted: i=1; AJvYcCUQYRv2gYnCjr6Yb8+sk9pjn8l1s4PxQz9yEehTPTMIavwuf1RWJ/5JINeTvnRNq190mOSwNRGjPJSismfd@lists.postgresql.org X-Gm-Message-State: AOJu0YzYRpiQURiiMFsl7pyGdHEZ4m9nYZVXEt64aUyf5nKuxLE3f7nb nI9yMcZDCCvP45DMWEad+rkayRQcQdUVnH5mwIZ/6MLbiJztTLsf0PP+wV9S5SJe3P8CXXKoSop WFPP4F96Qx5lS+J6Lg/Wp8kBy735x63j24tK8+YrIM2s3LqOKNUc= X-Google-Smtp-Source: AGHT+IFS5Uf5TicUr1GD4y40ZqZfRiR+W8UsXTn0ohQcB6i0yWRomGJ+GHATQj6oHjiWcP7y41FwWFXzJ4VTcbRKzDA= X-Received: by 2002:a05:6512:3d20:b0:536:53d1:850d with SMTP id 2adb3069b0e04-5367ff24bc6mr4862982e87.39.1726420423226; Sun, 15 Sep 2024 10:13:43 -0700 (PDT) MIME-Version: 1.0 References: <1aea530e4c96109b91fdde53a29e38beb625dc77.camel@kortschak.io> <20240723221121.51f2b3872d0ebfc36a6fa8ff@wanadoo.fr> <2f11b2ba-3182-492a-ab46-23cfa5ec913c@aklaver.com> <735913e4c9601a2a7ad57d2253d74451c42ba899.camel@kortschak.io> <21078220628bcebca0395a52d42b558ed965bbc0.camel@kortschak.io> <5c86256a4e83b1af73da22faab54889564e93129.camel@kortschak.io> <7320B905-E950-4035-9A13-8C9447AB52EC@gmail.com> <48019d21fd7c669afb83161337f7e007ae619534.camel@kortschak.io> <93c6b90cd39ae5fdf49cbd698e8de0c6b6f9bf3f.camel@kortschak.io> <90CC4567-4C9E-4F83-902C-A3CE5C3C74E5@gmail.com> In-Reply-To: <90CC4567-4C9E-4F83-902C-A3CE5C3C74E5@gmail.com> From: Willow Chargin Date: Sun, 15 Sep 2024 10:13:32 -0700 Message-ID: Subject: Re: re-novice coming back to pgsql: porting an SQLite update statement to postgres To: Alban Hertroys Cc: Dan Kortschak , pgsql-general@lists.postgresql.org Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: quoted-printable List-Id: List-Help: List-Subscribe: List-Post: List-Owner: List-Archive: Archived-At: Precedence: bulk On Sun, Sep 15, 2024 at 4:23=E2=80=AFAM Alban Hertroys = wrote: > > > On 15 Sep 2024, at 11:07, Dan Kortschak wrote: > > > > I have come to hopefully my last stumbling point. > > > > I am unable to see a way to express something like this SQLite syntax > > > > select json_group_array(json_replace(value, > > '$.a', case > > when json_extract(value, '$.a') > 2 then > > 2 > > else > > json_extract(value, '$.a') > > end, > > '$.b', case > > when json_extract(value, '$.b') < -2 then > > -2 > > else > > json_extract(value, '$.b') > > end > > )) > > from > > json_each('[{"a":1, "b":-3},{"a":2, "b":-2},{"a":3, "b":-1}]'); > > [...] > > I see basically two approaches. One is to take the objects apart [...] > > with t as ( > select jsonb($$[{"a":1, "b":-3, "c":1},{"a":2, "b":-2, "c":2},{"a= ":3, "b":-1, "c":3},{"a":3, "b":-3, "c":4}]$$) arr > ) > select jsonb_agg(jsonb_build_object( > 'a', case when records.a > 2 then 2 else records.a end > , 'b', case when records.b < -2 then -2 else records.b end > , 'c', c > )) > from t > cross join lateral jsonb_to_recordset(t.arr) records(a int, b int, c int) > ; > > [...] > > The drawback is that you have to specify all fields and types, but you do= n=E2=80=99t need to cast the values all the time either. Here is a variant of Alban's first method that does not require specifying all fields and types, and so works with heterogeneous values: WITH t AS ( SELECT jsonb($$[ {"a": 1, "b": -3, "c": 1}, {"a": 2, "b": -2, "c": 2}, {"a": 3, "b": -1, "c": 3}, {"a": 3, "b": -3, "c": 4} ]$$) arr ) SELECT jsonb_agg(new_element ORDER BY idx) new_arr FROM t, LATERAL ( SELECT idx, jsonb_object_agg(key, CASE WHEN key =3D 'a' THEN least(old_value::numeric, 2)::text::jsonb WHEN key =3D 'b' THEN greatest(old_value::numeric, -2)::text::jsonb ELSE old_value END) FROM jsonb_array_elements(arr) WITH ORDINALITY old_elements(old_element, idx), jsonb_each(old_element) each(key, old_value) GROUP BY idx ) new_elements(idx, new_element) I also took the liberties of using `least` / `greatest` to simplify the clamping operations, and using `WITH ORDINALITY` / `ORDER BY` on the array scan and re-aggregation to make the element ordering explicit rather than relying on the query engine to not re-order the rows. https://www.postgresql.org/docs/16/functions-conditional.html#FUNCTIONS-GRE= ATEST-LEAST https://www.postgresql.org/docs/16/queries-table-expressions.html#QUERIES-T= ABLEFUNCTIONS