2017-10-04 3 views
0

Je travaille sur une ancienne base de données héritée importée dans SQL Server 2012 à partir d'Oracle. J'ai le tableau suivant appelé INSOrders qui comprend une colonne appelée OrderID de type varchar(8).La division des données d'un enregistrement est une colonne spécifique T-SQL

Un exemple des données insérées est:

A04-05 | B81-02 | C02-01 
A01-01 | B95-01 | C99-05 
A02-02 | B06-07 | C03-02 
A98-06 | B10-01 | C17-01 
A78-07 | B02-03 | C15-03 
A79-01 | B02-01 | C78-06 

Première lettre = OrderType, à côté 2 chiffres = année - et dernier 2 chiffres = NumCommande dans cette année.

Je divisé toutes les données en trois colonnes: (non stockés, vient d'être présenté)

select 
    orderid, 
    substring(orderid, 0, patindex('%[0-9]%', orderid)) as ordtype, 
    right(max(datepart(yyyy, '01/01/' + substring(orderid, patindex('%[0-9]-%', orderid) - 1, 2))),2) as year, 
    max(substring(orderid, patindex('%-[0-9]%', orderid) + 1, 2)) as ordnum 
from 
    ins.insorders 
where 
    orderid is not null 
group by 
    substring(orderid, 0, patindex('%[0-9]%', orderid)), orderid 
order by 
    ordtype 

Il est à la recherche comme ceci:

OrderID | OrderType | OrderYear | OrderNum 
---------+-------------+-------------+---------- 
A04-05 | A   | 04   | 05 
A01-01 | A   | 01   | 01 
B10-03 | B   | 10   | 03 
B95-01 | B   | 95   | 01 
etc.... 

Mais maintenant, je veux simplement sélectionner Max Pour tout le OrderType: montrez seulement le maximum pour la lettre A, Montrez le maximum pour la lettre B, etc. Ce que je veux dire Max, je veux dire de la lettre AI doit montrer la dernière année et le dernier numéro de commande. Donc, si j'ai A04-01 et A04-02, montrez A04-02.

J'ai besoin de modifier ma requête ont été je peux voir ce qui suit:

OrderID | OrderType | OrderYear | OrderNum 
---------+-------------+-------------+---------- 
A04-05 | A   | 04   | 05 
B10-03 | B   | 10   | 03 
C17-01 | C   | 17   | 01 

Merci, je vraiment apprécier l'aide.

+1

C'est un peu bizarre, donc je suppose dans '' B10-03' OrderYear' montre '10' au lieu de' '95' parce 10' est représenté comme' '2010' et 95' est représentée comme '1995?' – Simon

+0

Cela ne serait-il pas aussi simple que d'utiliser MAX (orderid) et de supprimer orderid du groupe par? –

Répondre

1

Vous pouvez essayer ci-dessous. Utilisation de votre requête d'origine en tant que cte et attribution de numéros de ligne à chaque groupe de types de commande en fonction de l'année de la commande et du numéro de commande. Ensuite, obtenez tous les numéros de ligne 1 qui devrait être le maximum pour chaque type de commande.

Ce peu DATEPART(yyyy,('01/01/' + OrderYear)) fera en sorte que nous obtenons la bonne année de sorte que 95 est 1995 et 10 est 2010, etc.

;WITH cte 
    AS (
    select orderid, 
    substring(orderid, 0, patindex('%[0-9]%', orderid)) as ordtype, 
    right(max(datepart(yyyy,'01/01/' + substring(orderid, patindex('%[0-9]-%', orderid) - 1, 2))),2) as year, 
    max(substring(orderid, patindex('%-[0-9]%', orderid) + 1, 2)) as ordnum 
    from ins.insorders 
    where orderid is not null 
    group by substring(orderid, 0, patindex('%[0-9]%', orderid)), orderid 
    ) 

SELECT * 
FROM 
    (SELECT 
     * 
     , ROW_NUMBER() OVER (PARTITION BY OrderType ORDER BY DATEPART(yyyy,('01/01/' + OrderYear)) DESC, OrderNum DESC) AS RowNum 
    FROM cte) t 
WHERE t.RowNum = 1 
0

Les données sont mal représentées et j'ai seulement un moyen de « fromage », et nous aurons besoin de faire beaucoup d'hypothèses:

with cte_example 
as 
(your query) 
select OrderID 
     ,OrderType 
     ,OrderYear 
     ,OrderNum 
from 
(select *, row_number() over(partition by OrderType order by OrderYear DESC) rn  
from cte_example 
where OrderYear <= right(year(getdate()),2)) t1 
where t1.rn = 1 

Puisque vous avez déjà une requête extraire les informations que je ne prendra pas la peine de le changer. Nous Enveloppez votre requête dans un CTE, une requête à partir et appliquer la fonction row_number de décider qui OrderType a la plus récente OrderYear, ainsi que son OrderNum et OrderID

Maintenant, la partie la plus délicate est que les années sont mal représentés (en supposant que mon commentaire sur votre message d'origine est vrai), puis en utilisant toute sorte d'agrégation pour OrderTypeB renverra 95 car il est numériquement plus grand.

Nous supposons qu'aucune date de commande ne sera supérieure à cette année en cours, et que tout autre élément supérieur est dans les années 90, en utilisant cette instruction: where OrderYear < right(year(getdate()),2). En d'autres termes, obtenez cette année et les deux bons caractères. D'abord en récupérant 2017 de getdate puis 17 avec la fonction RIGHT. Je suis sûr que vous pouvez voir que c'est dangereux, parce que si votre dernière date est 1999? Donc, en les filtrant, nous pouvons voir la dernière année pour chaque OrderType ... espérons que cela aide.

Here est le test rextester que j'ai construit pour jouer avec votre requête au cas où vous voudriez l'essayer.

0

Je pense que votre requête initiale était presque exactement ce dont vous avez besoin, sauf que vous devez utiliser MAX (OrderID) et non le groupe.

declare @Something table 
(
    orderid varchar(6) 
) 

insert @Something 
(
    orderid 
) values 
('A04-05'), ('B81-02'), ('C02-01'), 
('A01-01'), ('B95-01'), ('C99-05'), 
('A02-02'), ('B06-07'), ('C03-02'), 
('A98-06'), ('B10-01'), ('C17-01'), 
('A78-07'), ('B02-03'), ('C15-03'), 
('A79-01'), ('B02-01'), ('C78-06') 

select max(orderid), 
substring(orderid, 0, patindex('%[0-9]%', orderid)) as ordtype, 
right(max(datepart(yyyy,'01/01/' + substring(orderid, patindex('%[0-9]-%', orderid) - 1, 2))),2) as year, 
max(substring(orderid, patindex('%-[0-9]%', orderid) + 1, 2)) as ordnum 
from myTable 
where orderid is not null 
group by substring(orderid, 0, patindex('%[0-9]%', orderid)) 
order by ordtype