Wählen Sie im LIKE Operator mehrere Werte aus


10

Ich habe eine SQL-Abfrage unten angegeben, ich möchte mehrere Werte mit dem likeOperator auswählen .

Ist meine Abfrage korrekt?

SELECT top 1 employee_id, employee_ident, utc_dt, rx_dt 
FROM       employee
INNER JOIN employee_mdata_history 
ON         employee.ident=employee_mdata_history.employee_ident 
WHERE      employee_id like 'emp1%' , 'emp3%' 
ORDER BY   rx_dt desc

Wenn nicht, kann mich jemand korrigieren?

Meine Tabelle enthält große Datenmengen, beginnend mit 'emp1'und 'emp3'. Kann ich das Ergebnis nach Top 3 "emp1" und Top 2 "emp3" basierend auf filtern rx_dt?

Antworten:


16

Alternativ können Sie die folgende Methode ausprobieren:

SELECT
  x.*
FROM
  (
    VALUES
      ('emp1%', 3),
      ('emp3%', 2)
  ) AS v (pattern, row_count)
  CROSS APPLY
  (  -- your query
    SELECT top (v.row_count)
               employee_id, employee_ident, utc_dt, rx_dt 
    FROM       employee
    INNER JOIN employee_mdata_history
    ON         employee.ident=employee_mdata_history.employee_ident 
    WHERE      employee_id like v.pattern
    ORDER BY   rx_dt desc
  ) AS x
;

Der VALUESZeilenkonstruktor stellt Ihre Musterliste als Tabelle dar und versorgt jedes Muster zusätzlich mit der Anzahl der Zeilen, die für dieses Muster abgerufen werden sollen. Der Operator CROSS APPLY wendet Ihre Abfrage auf jede Zeile der Musterliste an, dh auf jedes Muster, und begrenzt die Anzahl der Zeilen für jedes Muster auf den entsprechenden Wert aus der Musterliste.

Als Randnotiz möchte ich diese Gelegenheit nutzen, um vorzuschlagen, dass Sie Ihre Spalten in einer Abfrage, die aus zwei oder mehr Tabellen liest, immer mit dem Tabellenalias qualifizieren. Das macht Ihre Anfrage leichter lesbar / verständlich. Sie können immer kurze Aliase verwenden, um zu vermeiden, dass möglicherweise lange Tabellennamen wiederholt werden. Zum Beispiel:

SELECT TOP (1)
  e.employee_id,
  h.employee_ident,
  ...
FROM
  dbo.employee AS e
  INNER JOIN dbo.employee_mdata_history AS h
    ON e.ident = h.employee_ident
WHERE
  e.employee_id LIKE ...
ORDER BY
  ...

6

Sie sollten eine ODER / UND-Bedingung verwenden:

SELECT TOP (1) 
           employee_id, employee_ident, utc_dt, rx_dt 
FROM       employee
INNER JOIN employee_mdata_history 
ON         employee.ident = employee_mdata_history.employee_ident 
WHERE      employee_id like 'emp1%' 
OR         employee_id like 'emp3%' 
ORDER BY   rx_dt desc;

Schauen Sie sich OR (Transact-SQL) in MS-Docs an.

Ich habe ein Beispiel aufgestellt:

create table employees(employee_id varchar(10), employee_name varchar(100));

insert into employees values
('emp10', 'Bryan Nelson'),
('emp12', 'Rosalyn Sanders'),
('emp13', 'Rose Tudler'),
('emp20', 'Julio Gomez'),
('emp30', 'Ian McGregor'),
('emp40', 'Anne Hatt');
GO
SELECT employee_id, employee_name
FROM   employees
WHERE  employee_id LIKE 'emp1%'
OR     employee_id LIKE 'emp3%';
GO
employee_id | Mitarbeitername  
: ---------- | : --------------
emp10 | Bryan Nelson   
emp12 | Rosalyn Sanders
emp13 | Rose Tudler    
emp30 | Ian McGregor   

Denken Sie daran, dass Sie TOP 1 verwenden. Sie erhalten maximal eine Zeile, unabhängig davon, wie viele Bedingungen Sie verwenden.

SELECT TOP 1 employee_id, employee_name
FROM   employees
WHERE  employee_id LIKE 'emp1%'
OR     employee_id LIKE 'emp3%';
GO
employee_id | Mitarbeitername
: ---------- | : ------------
emp10 | Bryan Nelson

Wenn Sie die Zeilen TOP (X) WHERE employee_id LIKE 'emp1%'und TOP (X) benötigen WHERE employee_id LIKE 'emp3%', können Sie zwei select-Anweisungen verwenden, die mit UNION ALL verknüpft sind.

SELECT TOP 3 employee_id, employee_name
FROM   employees
WHERE  employee_id LIKE 'emp1%'
UNION ALL
SELECT TOP 1 employee_id, employee_name
FROM   employees
WHERE  employee_id LIKE 'emp3%'
GO
employee_id | Mitarbeitername  
: ---------- | : --------------
emp10 | Bryan Nelson   
emp12 | Rosalyn Sanders
emp13 | Rose Tudler    
emp30 | Ian McGregor   

Außerdem füge ich eine Mustersuche hinzu, aber diese Lösung gibt alle Datensätze zurück, die dem Muster entsprechen: LIKE 'emp [13]%'

SELECT employee_id, employee_name
FROM   employees
WHERE  employee_id LIKE 'emp[13]%'
GO
employee_id | Mitarbeitername  
: ---------- | : --------------
emp10 | Bryan Nelson   
emp12 | Rosalyn Sanders
emp13 | Rose Tudler    
emp30 | Ian McGregor   

dbfiddle hier


2

Ich denke du willst eine Reihe where employee_id like 'emp1%'und eine andere where employee_id like 'emp3%'. Eine Möglichkeit, dies zu erreichen, ist die Verwendung von union:

SELECT t1.*
FROM
  ( SELECT top 1 employee_id, employee_ident, utc_dt, rx_dt 
    FROM       employee
    JOIN employee_mdata_history 
        ON employee.ident=employee_mdata_history.employee_ident 
    WHERE employee_id like 'emp1%'
    ORDER BY rx_dt desc
  ) AS t1
UNION ALL
SELECT t2.*
FROM
  (  SELECT top 1 employee_id, employee_ident, utc_dt, rx_dt 
    FROM       employee
    JOIN employee_mdata_history 
        ON employee.ident=employee_mdata_history.employee_ident 
    WHERE employee_id like 'emp3%'
    ORDER BY rx_dt desc
  ) AS t2 ;

Da die Beine in der Verbindung garantiert disjunkt sind, UNION ALLkann a verwendet werden, und dies könnte ein Leistungsvorteil gegenüber der Verwendung von nur a sein UNION.

Ich glaube, SQL-Server 2008 unterstützt Fensterfunktionen wie row_number (), sodass Sie Folgendes verwenden können:

SELECT employee_id, employee_ident, utc_dt, rx_dt
FROM (
    SELECT employee_id, employee_ident, utc_dt, rx_dt
      , row_number() over (partition by substring(employee_id,1,4)
                           order by rx_dt desc) as rn 
    FROM employee
    JOIN employee_mdata_history 
        ON employee.ident = employee_mdata_history.employee_ident 
    WHERE employee_id like 'emp1%' 
       OR employee_id like 'emp3%'
) as T 
WHERE rn = 1 
ORDER BY rx_dt desc;

-2

Sie verwenden TOP(1)und order byKlausel. Sie erhalten also nur den ersten Top-Datensatz, der nach der Klausel geordnet ist.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.