2012-02-29 15 views
10

Tengo un "TBL" tabla que se parece a esto:Seleccione la primera fila coincidente

prod | cust | qty 
p1 | c1 | 5 
p1 | c2 | 10 
p2 | c1 | 2 
p3 | c2 | 8 

Lo que necesito es una lista distinta de pares de productos y clientes, pero sólo el primer cliente si el producto se vende a más de un cliente En otras palabras los resultados tienen que tener este aspecto:

prod | cust 
p1 | c1 
p2 | c1 
p3 | c2 

He intentado esto en todas las direcciones que se me ocurre, pero no acabo de obtener el resultado correcto. Claramente, ni el distinto ni el grupo por (por sí mismos) funcionarán, ya que ambos devolverán la fila p1, c2.

yo encontramos este question que es un partido muy cerrado, pero no puedo encontrar la manera de volver a escribir para conseguir que se haga lo que yo necesito.

Para colmo, actualmente esto tiene que funcionar en Access 2007 o posterior, pero en algún momento futuro también deberá funcionar en MySQL.

Crédito adicional a cualquier persona que también una los resultados a la tabla de clientes para que pueda buscar el nombre legible por humanos desde el código del cliente, p. c1 => Fred Bloggs Llaves

+1

¿Cómo se define "primer cliente"? ¿Hay algún campo de fecha que lo haga explícito que no se muestra? –

+0

Defino "primero" como el que devuelva la consulta. Me gustaría que me devolvieran p1, c1 o p1, c2. Simplemente no puedo hacer frente a que ambos sean devueltos (porque el código del producto se está utilizando en otra unión y no quiero duplicados). No hay otros campos útiles en la tabla tbl. – wobblycogs

+1

OK, leí este comentario después de publicar una respuesta, esto no tiene sentido, ¿quiere el "primer" cliente, pero realmente no le importa quién es el "primer" cliente o cómo se determina? No estoy escribiendo sus requisitos, pero realmente quiere resultados esencialmente aleatorios con el tiempo?!? –

Respuesta

13

Pregunta básica:

SELECT prod, MIN(cust) 
FROM yourTable 
GROUP BY prod 

Para el "Bono":

SELECT T.prod, 
     T.cust, 
     YC.SomeCustomerAttribute1, 
     YC.SomeCustomerAttribute2 
FROM (
     SELECT prod, MIN(cust) AS first_cust 
     FROM yourProducts 
     GROUP BY prod 
) AS T 
JOIN yourCustomers AS YC ON YC.cust = T.first_cust 
+1

+1 Aunque estoy empezando a sospechar que el OP solo quiere 'SELECT DISTINCT prod FROM table' – Fionnuala

+0

Muchas gracias por la respuesta, detectar lo que quería. Nunca se me ocurrió usar min. – wobblycogs

1

si sólo desea que el primer resultado de añadir LIMIT 1 a su consulta, o utilizar SELECT DISTINCT para obtener resultados únicos.

como para su unirse a comprobar esto:

SELECT * FROM TableA 
INNER JOIN TableB 
ON TableA.name = TableB.name 

esto hará que todas las filas con un juego de name tablaA y TableB.

EDITAR J Cooper que es correcto, ms-de acceso no tiene un equivalente a LIMIT. el más cercano es TOP, pero no creo que eso ayude. lo siento, no he usado el acceso desde la universidad.

+0

No quiero _just_ la primera fila. Quiero las filas p2, c1 y p3, c2 también. El límite causaría que simplemente devolvieran p1, c1. – wobblycogs

+2

Estoy bastante seguro de que ms-access no admite 'LIMIT'. –

2

voy a tener que asumir que usted tiene algún tipo de identificador que indica que es "primero". Una columna de fecha o una columna de identidad o algo.

En mi ejemplo, lo he hecho con una columna de identificación order_id.

CREATE TABLE products (
    order_id MEDIUMINT NOT NULL AUTO_INCREMENT, 
    prod char(2), 
    cust char(2), 
    qty int, 
    PRIMARY KEY (order_id) 
); 

INSERT INTO products (prod, cust, qty) VALUES 
    ('p1', 'c1', 5), 
    ('p1', 'c2', 10), 
    ('p2', 'c1', 2), 
    ('p3', 'c2', 8); 

Y a continuación, para obtener sus valores corren:

select p1.prod, p1.cust, p1.qty 
from products p1 
where not exists (select * from products p2 
       where p1.prod = p2.prod 
       and p2.order_id < p1.order_id) 

donde en cada línea de comprobar para ver si hay otros clientes que ordenaron que antes de lo que lo hizo. Si hay un pedido anterior, entonces no liste esta fila. (Por lo tanto, el not exists)

Esta es la sintaxis de mysql, por cierto, a la que dices que estás migrando. (Los expertos en acceso tendrían que editar esto de manera apropiada.)

Ahora, si no tiene una columna que identifique qué designa la secuencia de cuándo se ingresaron las órdenes, necesita una.Cualquier esquema que dependa de row_numbering implícito según el orden de inserción se desmoronará eventualmente, ya que no se garantiza que la "primera fila" permanezca igual.

+0

Por lo que sé MS Access no admite 'existe' –

+0

MS Access admite' exists'. – HansUp

+0

Puede que tenga razón sobre el acceso: uso muchas bases de datos, pero no acceso, lo cual supongo que es ANSI, pero evidentemente no lo es. Debería haber puesto el calificador más alto sobre mysql (que dice que necesita eventualmente). Continuaré enfatizando mi discusión de que para hacer algo real necesita algún tipo de identificador de secuencia/fecha y hora. Pero como solo quiere un resultado aleatorio, entonces lo que sea. . . –

0

"Primero" y "mínimo"() no son lo mismo. Si realmente quiere primero, intente esto:

declare @source table 
(
    prod varchar(10), 
    cust varchar(10), 
    qty int 
) 

insert into @source (prod, cust, qty) values ('p1', 'c1', 5) 
insert into @source (prod, cust, qty) values ('p1', 'c2', 10) 
insert into @source (prod, cust, qty) values ('p2', 'c1', 2) 
insert into @source (prod, cust, qty) values ('p3', 'c2', 8) 

select * from @source 

declare @target table 
(
    prod varchar(10), 
    cust varchar(10), 
    qty int 
) 

insert into @target (prod) 
select distinct prod from @source 

update @target 
set 
    cust = s.cust, 
    qty = s.qty 
from @source s 
join @target t on t.prod = s.prod 

select * from @target 
Cuestiones relacionadas