2011-01-15 18 views
5

¿Cómo puedo extraer los valores de un registro como comuns individuales en PostgreSQL¿Cómo puedo extraer los valores de un registro como columnas individuales en PostgreSQL

SELECT 
p.*, 
(SELECT ROW(id,server_id,format,product_id) FROM products_images pi WHERE pi.product_id = p.id LIMIT 1) AS image 

FROM products p 

WHERE p.company = 1 ORDER BY id ASC LIMIT 10 

En lugar de

image 
(3, 4, "jpeg", 7) 

me gustaría tener

id | server_id | format | product_id 
3 | 4   | jpeg | 7 

¿Hay alguna manera de seleccionar una sola imagen para cada producto y devolver las columnas d directamente en lugar de un registro?

+0

¿Por qué necesita para agrupar esos 4 columnas para una columna? –

+0

No necesito agruparlos, solo quiero tener una imagen para cada producto, pero no hay forma de poner LIMIT en una combinación como en mysql, lo mejor que logré fue la consulta anterior con ROW – codeassembly

Respuesta

0

Sólo especifique los componentes de su estructura:

SELECT a,b,c,image.id, image.server_id, ... 
FROM (

SELECT 
p.*, 
(SELECT ROW(id,server_id,format,product_id) FROM products_images pi WHERE pi.product_id = p.id LIMIT 1) AS image 

FROM products p 

WHERE p.company = 1 ORDER BY id ASC LIMIT 10 
) as subquery 

Pero de todos modos, me gustaría volver a trabajar la consulta y utilice una combinación en lugar de una subcláusula.

SELECT DISTINCT ON (p.*) p.*, 
     p.id,pi.server_id,pi.format,pi.product_id 
    FROM products p 
    LEFT JOIN product_images pi ON pi.product_id = p.id 
    WHERE p.company = 1 
    ORDER BY id ASC 
    LIMIT 10 

Pero yo creo que hay que especificar todos los campos-p en la distinta por separado para asegurar una sola imagen se carga por producto.

+0

. realmente funciona para ti? accediendo a los campos desde dentro de la fila usando la sintaxis 'image.id'? No puedo ejecutar eso para mi UDT ... –

+0

Obtengo 'ERROR: falta la entrada FROM-clause para la tabla "image"' para la primera consulta, y la segunda tampoco funciona "ERROR: SELECT DISTINCT ON debe coincidir con expresiones ORDER BY iniciales" También creo es más rápido ejecutar una subconsulta para cada producto (solo 10 en este caso) en lugar de unir todo y agregar DISTINCT, DISTINCT puede ser muy lento si las tablas son grandes. – codeassembly

+0

quería rechazar su respuesta por no probarlo en un código de prueba de concepto si la función ROW realmente utiliza los nombres de columna como los nombres de propiedad para struct. corrija su código o bórrelo (para que pueda ganar una insignia ** disciplinada) su código no funcionará, intente esto: 'select x.table_name from (seleccione row (table_name, column_name) x from information_schema.columns límite 1) como y' –

3

Prueba esto:

create type xxx as (t varchar, y varchar, z int); 

with a as 
(
select row(table_name, column_name, (random() * 100)::int) x 
from information_schema.columns 
) 
-- cannot cast directly to xxx, should cast to text first 
select (x::text::xxx).t, (x::text::xxx).y, (x::text::xxx).z 
from a 

Alternativamente, usted puede hacer esto:

with a as 
(
select row(table_name, column_name, (random() * 100)::int) x 
from information_schema.columns 
), 
-- cannot cast directly to xxx, should cast to text first 
b as (select x::text::xxx as w from a) 

select 
(w).t, (w).y, (w).z 
from b 

Para seleccionar todos los campos:

with a as 
(
select row(table_name, column_name, (random() * 100)::int) x 
from information_schema.columns 
), 
-- cannot cast directly to xxx, should cast to text first 
b as (select x::text::xxx as w from a) 

select 
(w).* 
from b 

Puede hacer esto también, pero esto hace que el Todo el ejercicio de usar ROW es inútil cuando simplemente se puede eliminar la función ROW y volver a recogerla desde afuera de cte/derivada tabl mi. Supuse que la FILA del OP venía de una función; para lo cual debe utilizar los códigos de arriba, no el siguiente:

with a as 
(
select row(table_name, column_name, (random() * 100)::int)::xxx x 
from information_schema.columns 
) 
select 
(x).t, (x).y, (x).z 
from a 
+0

que parece ser mucho trabajo para mi consulta simple, así que supongo que usar ROW no es una buena solución para mi problema principal, extraer una fila de la tabla de imágenes para cada fila de producto. – codeassembly

+0

de hecho, es por eso que, en primer lugar, le pregunto por qué necesita agrupar columnas en una columna –

0

probar esto, funcionará en su código existente con modificaciones mínimas (si la creación de un tipo es una modificación mínima para usted ;-)

create type image_type as (id int, server_id int, format varchar, product_id int); 

SELECT 
p.*, 
((SELECT ROW(id,server_id,format,product_id) 
    FROM products_images pi 
    WHERE pi.product_id = p.id LIMIT 1)::text::image_type).* 

FROM products p 

WHERE p.company = 1 ORDER BY id ASC LIMIT 10 

Prueba de concepto de código:

Crea primer tipo:

create type your_type_here as (table_name varchar, column_name varchar) 

co real de:

select 
a.b, 
((select row(table_name, column_name) 
    from information_schema.columns limit 1)::text::your_type_here).* 
from generate_series(1,10) as a(b) 

Pero supongo que debe hacer frente con GROUP BY' and MAX combo or use ON` DISTINCT parecido a lo que Daniel ha publicado

Cuestiones relacionadas