Konuyu Oyla:
  • Derecelendirme: 0/5 - 0 oy
  • 1
  • 2
  • 3
  • 4
  • 5
Son Alis Tarihine Göre bir ürünün fiyatı nasıl bulunur
#11
slm kardeşim
en garantisi triger kullanman bunun haricinde tüm kodlar problem yaşatacatır.
biliyorsun muhasebeciler her zaman faturalar işlenirken tarih sırasına göre işlerler bu sebeple en kolay yöntem triger oluşturmak bu sunucuyuda yormaz senide delphi kodlama derdinden kurtarır
yok delphi ile komut ile tetikleyeyim istiyorsan bir procedure yazmanı tavsiye ederim,
ama zaten bu işin daha iyisini triger yapar (işlenen son faturadaki ürün fiyatlarını alıp ürün listesine son alış fiyatı olarak işleyebilirsin).
Cevapla
#12
(28-08-2020, Saat: 11:06)adelphiforumz Adlı Kullanıcıdan Alıntı: Merhaba Arkadaşlar

MS SQL üzerinde 2 adet tablom yer alıyor bu tablolardan 1 tanesi Master (Alis) diğeri Detail (AlisDetay) seklinde 
Bu tablolar içerisinde gelen faturalar ve içeriğindeki ürünler tutuluyor.

Şimdi geleyim problemin detayına
Amacım gelen faturalar içerisindeki ürünlerin son geliş tarihine göre son fiyatını almaya çalışıyorum
Aynı tarih içerisinde aynı ürün için 1 den fazla fatura gelebilmektedir. 
Bu durumda son kayıt edilen ürünün fiyatı geçerli olacaktır. 
Bunu sağlayan AlisDetay tablosundaki IdAlisDetay alanıdır.

NOT
Bu işlemi bir alt fonksiyon yazmadan yapmaya çalışıyorum.
IdUrun ve Fiyat şeklinde olanı aşağıdaki scriptte yer aldığı şekilde çözümlendi.
Fakat IdUrun, FaturaTarihi, NetFiyat şeklinde daha pratik bir çözüm yolu varmıdır.
Amacım bu sorguyu bir view yada procedure haline getirip AlisDetay tablosundaki tüm ürünlerin son alış tarihini ve son fiyatlarını bir liste halinde elde etmektir.

Şimdiden zaman ayıran arkadaşlara teşekkürler

ÖRNEK Tablolar, Örnek sorgu ve Veri içerikleri aşağıdaki şekildedir.

   select SONFATID.IdUrun, Dty.NetFiyat
   from (select TRHLI.IdUrun, max(TUMLISTE.IdAlis) as SONID
           from (select AD.IdUrun, max(A.FaturaTarihi) as SONTARIH
                   from AlisDetay AD
                        inner join Alis A on A.IdAlis = AD.IdAlis
                  group by AD.IdUrun
                 ) as TRHLI
                 inner join (select AD.IdUrun, A.FaturaTarihi, A.IdAlis
                               from AlisDetay AD
                                    inner join Alis A on A.IdAlis = AD.IdAlis) as TUMLISTE on TUMLISTE.IdUrun = TRHLI.IdUrun and TUMLISTE.FaturaTarihi = TRHLI.SONTARIH
                              group by TRHLI.IdUrun) as SONFATID
                 inner join AlisDetay Dty on Dty.IdUrun = SONFATID.IdUrun and Dty.IdAlis = SONFATID.SONID


USE [TEST]
GO
/****** Object:  Table [dbo].[Alis]    Script Date: 27.08.2020 17:45:10 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[Alis](
[IdAlis] [int] NOT NULL,
[FaturaTarihi] [datetime] NULL,
CONSTRAINT [PK_Alis] PRIMARY KEY CLUSTERED
(
[IdAlis] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO
/****** Object:  Table [dbo].[AlisDetay]    Script Date: 27.08.2020 17:45:10 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[AlisDetay](
[IdAlisDetay] [int] IDENTITY(1,1) NOT NULL,
[IdAlis] [int] NULL,
[IdUrun] [int] NULL,
[NetFiyat] [decimal](18, 2) NULL,
CONSTRAINT [PK_AlisDetay] PRIMARY KEY CLUSTERED
(
[IdAlisDetay] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO
INSERT [dbo].[Alis] ([IdAlis], [FaturaTarihi]) VALUES (1, CAST(N'2020-08-01T00:00:00.000' AS DateTime))
GO
INSERT [dbo].[Alis] ([IdAlis], [FaturaTarihi]) VALUES (2, CAST(N'2020-08-01T00:00:00.000' AS DateTime))
GO
INSERT [dbo].[Alis] ([IdAlis], [FaturaTarihi]) VALUES (3, CAST(N'2020-08-01T00:00:00.000' AS DateTime))
GO
INSERT [dbo].[Alis] ([IdAlis], [FaturaTarihi]) VALUES (4, CAST(N'2020-08-05T00:00:00.000' AS DateTime))
GO
INSERT [dbo].[Alis] ([IdAlis], [FaturaTarihi]) VALUES (5, CAST(N'2020-08-05T00:00:00.000' AS DateTime))
GO
INSERT [dbo].[Alis] ([IdAlis], [FaturaTarihi]) VALUES (6, CAST(N'2020-08-06T00:00:00.000' AS DateTime))
GO
INSERT [dbo].[Alis] ([IdAlis], [FaturaTarihi]) VALUES (7, CAST(N'2020-08-06T00:00:00.000' AS DateTime))
GO
INSERT [dbo].[Alis] ([IdAlis], [FaturaTarihi]) VALUES (8, CAST(N'2020-08-06T00:00:00.000' AS DateTime))
GO
INSERT [dbo].[Alis] ([IdAlis], [FaturaTarihi]) VALUES (9, CAST(N'2020-08-06T00:00:00.000' AS DateTime))
GO
SET IDENTITY_INSERT [dbo].[AlisDetay] ON
GO
INSERT [dbo].[AlisDetay] ([IdAlisDetay], [IdAlis], [IdUrun], [NetFiyat]) VALUES (1, 1, 1, CAST(5.00 AS Decimal(18, 2)))
GO
INSERT [dbo].[AlisDetay] ([IdAlisDetay], [IdAlis], [IdUrun], [NetFiyat]) VALUES (2, 1, 2, CAST(5.00 AS Decimal(18, 2)))
GO
INSERT [dbo].[AlisDetay] ([IdAlisDetay], [IdAlis], [IdUrun], [NetFiyat]) VALUES (3, 1, 3, CAST(5.00 AS Decimal(18, 2)))
GO
INSERT [dbo].[AlisDetay] ([IdAlisDetay], [IdAlis], [IdUrun], [NetFiyat]) VALUES (4, 2, 1, CAST(3.00 AS Decimal(18, 2)))
GO
INSERT [dbo].[AlisDetay] ([IdAlisDetay], [IdAlis], [IdUrun], [NetFiyat]) VALUES (5, 2, 2, CAST(3.00 AS Decimal(18, 2)))
GO
INSERT [dbo].[AlisDetay] ([IdAlisDetay], [IdAlis], [IdUrun], [NetFiyat]) VALUES (6, 2, 2, CAST(3.00 AS Decimal(18, 2)))
GO
INSERT [dbo].[AlisDetay] ([IdAlisDetay], [IdAlis], [IdUrun], [NetFiyat]) VALUES (7, 3, 1, CAST(2.00 AS Decimal(18, 2)))
GO
INSERT [dbo].[AlisDetay] ([IdAlisDetay], [IdAlis], [IdUrun], [NetFiyat]) VALUES (8, 3, 2, CAST(2.00 AS Decimal(18, 2)))
GO
INSERT [dbo].[AlisDetay] ([IdAlisDetay], [IdAlis], [IdUrun], [NetFiyat]) VALUES (9, 3, 3, CAST(2.00 AS Decimal(18, 2)))
GO
INSERT [dbo].[AlisDetay] ([IdAlisDetay], [IdAlis], [IdUrun], [NetFiyat]) VALUES (10, 4, 1, CAST(10.00 AS Decimal(18, 2)))
GO
INSERT [dbo].[AlisDetay] ([IdAlisDetay], [IdAlis], [IdUrun], [NetFiyat]) VALUES (11, 4, 2, CAST(5.00 AS Decimal(18, 2)))
GO
INSERT [dbo].[AlisDetay] ([IdAlisDetay], [IdAlis], [IdUrun], [NetFiyat]) VALUES (12, 5, 3, CAST(3.00 AS Decimal(18, 2)))
GO
INSERT [dbo].[AlisDetay] ([IdAlisDetay], [IdAlis], [IdUrun], [NetFiyat]) VALUES (13, 6, 1, CAST(4.00 AS Decimal(18, 2)))
GO
INSERT [dbo].[AlisDetay] ([IdAlisDetay], [IdAlis], [IdUrun], [NetFiyat]) VALUES (14, 6, 2, CAST(4.00 AS Decimal(18, 2)))
GO
INSERT [dbo].[AlisDetay] ([IdAlisDetay], [IdAlis], [IdUrun], [NetFiyat]) VALUES (15, 6, 3, CAST(4.00 AS Decimal(18, 2)))
GO
INSERT [dbo].[AlisDetay] ([IdAlisDetay], [IdAlis], [IdUrun], [NetFiyat]) VALUES (16, 7, 2, CAST(8.00 AS Decimal(18, 2)))
GO
INSERT [dbo].[AlisDetay] ([IdAlisDetay], [IdAlis], [IdUrun], [NetFiyat]) VALUES (17, 8, 1, CAST(2.00 AS Decimal(18, 2)))
GO
INSERT [dbo].[AlisDetay] ([IdAlisDetay], [IdAlis], [IdUrun], [NetFiyat]) VALUES (18, 8, 2, CAST(6.50 AS Decimal(18, 2)))
GO
INSERT [dbo].[AlisDetay] ([IdAlisDetay], [IdAlis], [IdUrun], [NetFiyat]) VALUES (19, 9, 1, CAST(3.50 AS Decimal(18, 2)))
GO
INSERT [dbo].[AlisDetay] ([IdAlisDetay], [IdAlis], [IdUrun], [NetFiyat]) VALUES (20, 9, 2, CAST(4.50 AS Decimal(18, 2)))
GO
INSERT [dbo].[AlisDetay] ([IdAlisDetay], [IdAlis], [IdUrun], [NetFiyat]) VALUES (21, 9, 3, CAST(5.50 AS Decimal(18, 2)))
GO
SET IDENTITY_INSERT [dbo].[AlisDetay] OFF
GO

Ürünlerin son alış fiyatını almak için aşağıdaki benzeri bir SQL kodu kullanabilirsiniz. Ben kodu test edebilmek için kendi veritabanı yapıma göre yazdım. Siz TABLE ve COULUMN adlarını, sorgu koşullarını  kendinize göre düzeltirsiniz.

SELECT 
 TBL_SON_FIYAT.* 
FROM (
     SELECT
       ROW_NUMBER() OVER (PARTITION BY AlisDetay.STOK_REF ORDER BY AlisDetay.STOK_REF, Alis.TRH DESC) AS SIRA_NO,
       AlisDetay.STOK_REF,
       Alis.TRH AS FATURA_TRH,
       Alis.BELGE_NO AS FATURA_NO,
       AlisDetay.FIYAT
     FROM
       TBL_STOKFISDET AlisDetay
       LEFT OUTER JOIN TBL_STOKFIS Alis ON (AlisDetay.STOKFIS_REF = Alis.REF)
     ) TBL_SON_FIYAT
WHERE
 TBL_SON_FIYAT.SIRA_NO = 1

Şimdi bu kodu stok tablomla veya başka herhangi bir tabloyla birleştirmek istersem ortaya:

SELECT
 STOK.KOD,
 STOK.ADI,
 SON_FIYAT.FATURA_TRH,
 SON_FIYAT.FATURA_NO,
 SON_FIYAT.FIYAT
FROM
 TBL_STOK STOK
 LEFT OUTER JOIN (

               SELECT 
                 TBL_SON_FIYAT.* 
               FROM (
                     SELECT
                       ROW_NUMBER() OVER (PARTITION BY AlisDetay.STOK_REF ORDER BY AlisDetay.STOK_REF, Alis.TRH DESC) AS SIRA_NO,
                       AlisDetay.STOK_REF,
                       Alis.TRH AS FATURA_TRH,
                       Alis.BELGE_NO AS FATURA_NO,
                       AlisDetay.FIYAT
                     FROM
                       TBL_STOKFISDET AlisDetay
                       LEFT OUTER JOIN TBL_STOKFIS Alis ON (AlisDetay.STOKFIS_REF = Alis.REF)
                     ) TBL_SON_FIYAT
               WHERE
                 TBL_SON_FIYAT.SIRA_NO = 1
               ) SON_FIYAT ON (STOK.REF = SON_FIYAT.STOK_REF)
 


şeklinde bir kod çıkacaktır. Takıldığınız yer olursa yardımcı olmaya çalışırım.
WWW
Cevapla
#13
@csunguray paylaşım için teşekkürler
benim yazdığım örnek ile @uparlayan nın verdiği örneklerin karması şeklinde olmuş sizinkide farklı bir bakış açısı sonuç aynı
Bu dünyada kendine sakladığın bilgi ahirette işine yaramaz. 
Cevapla
#14
Performans olarak incelemek gerekebilir sorguları ama başka bir yöntem de benden olsun. Bu yapı SQL Server özelinde kalabilir yalnız.
select ana.*, detay.* from Alis ana
cross apply (select top 1 * from AlisDetay alt where alt.IdAlis=ana.IdAlis order by Tarih desc, SiraNo desc) detay
cross apply içinde kullanılan tablonun where şartında (belki order by ile sıralamada kullanılan alanlarında da) indeks tanımlı ise performans sıkıntısı çıkmaz diye tahmin ediyorum.
Cevapla
#15
Merhaba Cross Apply ile sorgu zamanı uzun sürüyor.  Alttaki gibi de yapabilirsiniz. Tablo ismi ve Field isimlerini kendinize göre değiştiriniz.

 
SELECT 
(
SELECT TOP 1 FD.BIRIMFIYAT 
FROM FISDETAY FD  WITH (NOLOCK) INNER JOIN 
FISBASLIK FB WITH (NOLOCK) ON FD.FISID = FB.ID WHERE FD.URUNID = U.ID 
ORDER BY FB.TARIH DESC
) SONFIYAT,
   U.* FROM URUN U WITH (NOLOCK)
WWW
Cevapla
#16
Cross apply'in yavaş çalışma sebebi her satır için buradaki sorguyu tekrar tekrar çalıştırmasından kaynaklıdır. Aynı yavaşlık bu mantıkla yazılan bir alan değeri getirmek için çağrılan alt tablo sorgusu için de geçerlidir. Hatta alt tablo boşsa sizin belirttiğiniz yöntemi bire bir karşılayan outer apply olacaktır. Zira detayı olmayan kayıtlar cross aply sorguda gelmeyecektir.

Eğer sorgulanan tek alan ise her iki yöntem arasında performans olarak pek bir fark yoktur ama alt sorgudan başka alanlara da ihtiyaç duyulursa outer (ya da cross) apply tekrar tekrar çalıştırılmaz. Elimde yaklaşık ana tabloda 72000 x alt tabloda 236000 kayıt olan bir sorguda deneme yaptım ve calculated alan değeri üzerinden sıralama yaparak test ettiğimde tek alan çağrısında ikisi de aynı performansı gösterdi (yaklaşık 4 sn) fakat alt tablodan 3 alan çektiğimde outer apply doğal olarak yine 4 sn sürdü ama diğer yöntem yaklaşık 10 sn sürdü.
Cevapla
#17
Bir öneri : Eğer faturalardan hareket ederek son alış fiyatını buluyorsanız ve Alışlar tablosunda satıştan iadeleri de tutuyor iseniz sorguda bunu da göz önünde bulundurunuz.
Bilmeyen ve bilmediğini bilen çocuktur, ona öğretin.
Bilen ve bildiğini bilmeyen uykudadır, onu uyandırın.
Bilmeyen ve bilmediğini bilmeyen aptaldır, ondan sakının.
Bilen ve bildiğini bilen öncüdür, onu izleyin.
WWW
Cevapla


Konu ile Alakalı Benzer Konular
Konular Yazar Yorumlar Okunma Son Yorum
  SQl Server içinde değere göre kontrol yapmak Bay_Y 6 2.566 22-08-2018, Saat: 23:34
Son Yorum: Bay_Y
  SQL Server Management Studio Nasıl Onarılır ? DelphiCanR 0 1.429 03-05-2017, Saat: 10:46
Son Yorum: DelphiCanR



Konuyu Okuyanlar: 1 Ziyaretçi