Domanda

Quando si utilizza la funzione SQL MIN (), insieme a GROUP BY, saranno eventuali ulteriori colonne (non la colonna MIN, o uno del gruppo per colonne) corrispondere ai dati nella riga corrispondente MIN?

Ad esempio, data una tabella con i nomi di reparto, i nomi dei dipendenti e lo stipendio:

SELECT MIN(e.salary), e.* FROM employee e GROUP BY department

Ovviamente vado a prendere due buoni colonne, il salario minimo e il reparto. Saranno il nome del dipendente (e qualsiasi altro campo dei dipendenti) sia dalla stessa riga? Ossia la riga con il MIN (stipendio)?

So che ci potrebbe essere molto probabilmente due dipendenti con lo stesso (e più bassa) lo stipendio, ma tutto quello che mi preoccupa (ora) sta ottenendo tutte le informazioni sul (o un singolo ) più economico dei dipendenti.

Sarebbe questo selezionare il venditore più economico?

SELECT min(salary), e.* FROM employee e WHERE department = 'sales'

In sostanza, posso essere sicuro che i dati restituiti con la funzione MIN () sarà partite il record (o un singolo ) con il valore minimo?

Se le questioni di database, sto lavorando con MySql.

È stato utile?

Soluzione

Se si voleva ottenere il dipendente "più economico" in ogni reparto si avrebbe due scelte fuori della parte superiore della mia testa:

SELECT
     E.*     -- Don't actually use *, list out all of your columns
FROM
     Employees E
INNER JOIN
     (
          SELECT
               department,
               MIN(salary) AS min_salary
          FROM
               Employees
          GROUP BY
               department
     ) AS SQ ON
     SQ.department = E.department AND
     SQ.min_salary = E.salary

In alternativa si può usare:

SELECT
     E.*
FROM
     Employees E1
LEFT OUTER JOIN Employees E2 ON
     E2.department = E1.department AND
     E2.salary < E1.salary
WHERE
     E2.employee_id IS NULL -- You can use any NOT NULL column here

La seconda affermazione funziona in modo efficace dicendo, mi mostra tutti i dipendenti in cui non si può trovare un altro dipendente nello stesso dipartimento, con un salario inferiore.

In entrambi i casi, se due o più dipendenti hanno stipendi uguali che sono il minimo si ottengono entrambi (tutti).

Altri suggerimenti

SELECT  e.*
FROM    employee e
WHERE   e.id =
        (
        SELECT  id
        FROM    employee ei
        WHERE   ei.department = 'sales'
        ORDER BY
                e.salary
        LIMIT 1
        )

Per ottenere i valori per ogni reparto, uso:

SELECT  e.*
FROM    department d
LEFT JOIN
        employee e
ON   e.id =
        (
        SELECT  id
        FROM    employee ei
        WHERE   ei.department = d.id
        ORDER BY
                e.salary
        LIMIT 1
        )

Per ottenere i valori solo per quei reparti che hanno dipendenti, uso:

SELECT  e.*
FROM    (
        SELECT  DISTINCT eo.department
        FROM    employee eo
        ) d
JOIN
        employee e
ON   e.id =
        (
        SELECT  id
        FROM    employee ei
        WHERE   ei.department = d.department
        ORDER BY
                e.salary
        LIMIT 1
        )

Naturalmente, avere un indice su (department, salary) migliorerà notevolmente tutte e tre le domande.

La soluzione più veloce:

SET @dep := '';
SELECT * FROM (
  SELECT * FROM `employee` ORDER BY `department`, `salary`
) AS t WHERE IF ( @dep = t.`department`, FALSE, ( @dep := t.`department` ) OR TRUE );

Un altro approccio può essere utilizzando funzioni analitiche. Ecco la query utilizzando funzioni analitiche e row_num

SELECT nome, stipendio da (first_name di selezione, di stipendio, row_number () su (PARTITION BY DEPARTMENT_ID ORDER BY stipendio ASC) come row_count dai dipendenti) in cui row_count = 1;

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top