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
#18
Merhaba benım onerım su sekılde

 SELECT al.IdAlis,
       al.FaturaTarihi,
       a.IdAlisDetay,
       a.IdUrun,
       a.NetFiyat
FROM AlisDetay a
JOIN Alis al on Al.IdAlis=a.IdAlis
JOIN (SELECT max(da.IdAlisDetay) AS IdAlisDetay
      FROM AlisDetay da 
      GROUP BY da.IdUrun
     ) T ON T.IdAlisDetay=a.IdAlisDetay
Cevapla
#19
(25-09-2020, Saat: 19:06)serdar Adlı Kullanıcıdan Alıntı: Merhaba benım onerım su sekılde

 SELECT al.IdAlis,
       al.FaturaTarihi,
       a.IdAlisDetay,
       a.IdUrun,
       a.NetFiyat
FROM AlisDetay a
JOIN Alis al on Al.IdAlis=a.IdAlis
JOIN (SELECT max(da.IdAlisDetay) AS IdAlisDetay
      FROM AlisDetay da 
      GROUP BY da.IdUrun
     ) T ON T.IdAlisDetay=a.IdAlisDetay

id'si en büyük olan alış, hareketin son alış olduğu anlamına gelmez. alış hareketenin tarihine hiç bakmadan son alışı bulmak felaket olacaktır. bu sql yanlış sonuç verir.
Cevapla
#20
@bibilen gecmis tarihe kayit eklenebilir haklisin simdi farkettim. Ama ayni tarihe ayni urunden alis yaparsa hangisinin sonuncu oldugunu nasil belirleycegiz? Sanirim zamanin tekilligi saglanmali. Yani tarih alani datetime ve (tarih,idurun) ikilisine unique index verilirse sorun ortadan kalkar diye dusunuyorum
Cevapla


Konu ile Alakalı Benzer Konular
Konular Yazar Yorumlar Okunma Son Yorum
  Trew View yapısında olan veriden Root kaydına nasıl ulaşılır adelphiforumz 9 819 25-12-2023, Saat: 08:06
Son Yorum: adelphiforumz
  Tarihin ayın kaçıncı haftası olduğu nasıl bulunur (Çözüldü) adelphiforumz 3 539 19-10-2023, Saat: 12:27
Son Yorum: serdar
  MSSQL TableType tipinde parametre nasıl geçilir? adelphiforumz 28 7.310 29-12-2021, Saat: 11:37
Son Yorum: mrmarman
  Değer ve yetkiye göre sorgulama denizfatihi 0 723 26-09-2021, Saat: 12:23
Son Yorum: denizfatihi
  Recursive işlem ve Update Nasıl yapılır adelphiforumz 10 3.933 14-02-2021, Saat: 22:46
Son Yorum: serdar



Konuyu Okuyanlar: 1 Ziyaretçi