Access
 sql >> Teknologi Basis Data >  >> RDS >> Access

Melaporkan Lebih Mendetail Dari Biasanya – Microsoft Access

Pelaporan Lebih Mendetail Dari Biasanya – Microsoft Access

Biasanya, ketika kami melakukan pelaporan, kami biasanya melakukannya dengan perincian yang lebih tinggi. Misalnya, klien biasanya menginginkan laporan penjualan bulanan. Basis data akan menyimpan penjualan individu sebagai satu catatan, jadi tidak ada masalah untuk menjumlahkan angka ke bulan masing-masing. Sama dengan tahun, atau bahkan beralih dari sub-kategori ke kategori.

Tapi misalkan mereka harus turun ? Kemungkinan besar, jawabannya adalah “desain database tidak bagus. buang dan mulai lagi!” Bagaimanapun, memiliki perincian yang tepat untuk data Anda sangat penting untuk database yang solid. Tapi ini bukan kasus di mana normalisasi tidak dilakukan. Mari kita pertimbangkan kebutuhan untuk membuat akun inventaris dan pendapatan, dan menanganinya dengan cara FIFO. Saya akan minggir dengan cepat untuk menunjukkan bahwa saya bukan CBA, dan setiap klaim akuntansi yang saya buat harus diperlakukan dengan penuh kecurigaan. Jika ragu, hubungi akuntan Anda.

Dengan penyangkalan, mari kita lihat bagaimana kami saat ini menyimpan data. Dalam contoh ini, kita perlu mencatat pembelian produk, lalu kita harus mencatat penjualan pembelian yang baru saja kita beli.

Misalkan untuk satu produk kita memiliki 3 pembelian:
Date | Qty | Per-Cost
9/03 | 3 | $45
9/08 | 6 | $40
9/09 | 8 | $50

Kami kemudian menjual produk tersebut pada kesempatan yang berbeda dengan harga yang berbeda:
Date | Qty | Per-Price
9/05 | 2 | $60
9/07 | 1 | $55
9/10 | 4 | $50
9/12 | 3 | $60
9/15 | 3 | $65
9/19 | 4 | $55

Perhatikan bahwa granularitas berada pada tingkat transaksi — kami membuat satu catatan untuk setiap pembelian dan untuk setiap pesanan. Ini sangat umum dan masuk akal – kita hanya perlu memasukkan jumlah produk yang kita jual, dengan harga tertentu untuk transaksi tertentu.

Oke, di mana hal-hal akuntansi yang Anda tolak?

Untuk laporan, kita harus menghitung pendapatan yang kita hasilkan pada setiap unit produk. Mereka memberi tahu saya bahwa mereka harus memproses produk dengan cara FIFO… yaitu, unit produk pertama yang dibeli harus menjadi unit produk pertama yang dipesan. Untuk kemudian menghitung margin yang kami buat pada unit produk tersebut, kami harus mencari biaya unit produk tertentu kemudian dikurangi dari harga yang dipesan.

Margin kotor =pendapatan produk – biaya produk

Tidak ada yang menghancurkan bumi, tapi tunggu, lihat pembelian dan pesanannya! Kami hanya memiliki 3 pembelian, dengan 3 titik biaya yang berbeda, kemudian kami memiliki 6 pesanan dengan 3 titik harga yang berbeda. Titik biaya mana yang menuju titik harga mana?

Rumus sederhana untuk menghitung margin kotor ini, dengan cara FIFO sekarang mengharuskan kita untuk pergi ke perincian unit individu produk. Kami tidak memiliki tempat di database kami. Saya membayangkan bahwa jika saya menyarankan agar pengguna memasukkan satu catatan per unit produk, akan ada protes yang cukup keras dan mungkin beberapa pemanggilan nama. Jadi, apa yang harus dilakukan?

Memutusnya

Katakanlah untuk tujuan akuntansi, kami akan menggunakan tanggal pembelian untuk mengurutkan setiap unit produk. Ini adalah bagaimana seharusnya keluar:
Line # | Purch Date | Order Date | Per-Cost | Per-Price
1 | 9/03 | 9/05 | $45 | $60
2 | 9/03 | 9/05 | $45 | $60
3 | 9/03 | 9/07 | $45 | $55
4 | 9/08 | 9/10 | $40 | $50
5 | 9/08 | 9/10 | $40 | $50
6 | 9/08 | 9/10 | $40 | $50
7 | 9/08 | 9/10 | $40 | $50
8 | 9/08 | 9/12 | $40 | $60
9 | 9/08 | 9/12 | $40 | $60
10 | 9/09 | 9/12 | $50 | $60
11 | 9/09 | 9/15 | $50 | $65
12 | 9/09 | 9/15 | $50 | $65
13 | 9/09 | 9/15 | $50 | $65
14 | 9/09 | 9/19 | $50 | $55
15 | 9/09 | 9/19 | $50 | $55
16 | 9/09 | 9/19 | $50 | $55
17 | 9/09 | 9/19 | $50 | $55

Jika Anda mempelajari rinciannya, Anda dapat melihat bahwa ada tumpang tindih di mana kami mengkonsumsi beberapa produk dari satu pembelian untuk pesanan anu sementara waktu lain kami memiliki pesanan yang dipenuhi oleh pembelian yang berbeda.

Seperti disebutkan sebelumnya, kami sebenarnya tidak memiliki 17 baris itu di mana pun di database. Kami hanya memiliki 3 baris pembelian dan 6 baris pesanan. Bagaimana kita mendapatkan 17 baris dari kedua tabel?

Menambahkan lebih banyak lumpur

Tapi kita belum selesai. Saya baru saja memberi Anda contoh ideal di mana kami kebetulan memiliki keseimbangan sempurna dari 17 unit yang dibeli yang diimbangi oleh 17 unit pesanan untuk produk yang sama. Dalam kehidupan nyata, itu tidak seindah itu. Terkadang kita dibiarkan dengan kelebihan produk. Bergantung pada model bisnisnya, mungkin juga menyimpan lebih banyak pesanan daripada yang tersedia di inventaris. Mereka yang bermain pasar saham mengenali seperti short-selling.

Kemungkinan terjadinya ketidakseimbangan juga menjadi alasan mengapa kita tidak bisa mengambil jalan pintas dengan hanya menjumlahkan semua biaya dan harga, kemudian dikurangi untuk mendapatkan margin. Jika kita memiliki X unit, kita perlu mengetahui titik biaya mana untuk menghitung persediaan. Demikian pula, kami tidak dapat berasumsi bahwa pesanan yang tidak terpenuhi akan dipenuhi dengan rapi oleh satu pembelian dengan satu titik biaya. Jadi, perhitungan yang kami lakukan tidak hanya harus berfungsi untuk contoh ideal, tetapi juga untuk tempat kami memiliki persediaan berlebih atau pesanan yang tidak terpenuhi.

Pertama-tama mari kita berurusan dengan masalah menghitung berapa banyak init produk yang perlu kita pertimbangkan. Jelas bahwa SUM() sederhana dari jumlah unit yang dipesan atau jumlah unit yang dibeli tidak akan cukup. Tidak, sebaliknya, kita harus SUM() baik jumlah produk yang dibeli maupun jumlah produk yang dipesan. Kami kemudian akan membandingkan SUM()s dan memilih yang lebih tinggi. Kita bisa mulai dengan kueri ini:
WITH ProductPurchaseCount AS (
SELECT
p.ProductID,
SUM(p.QtyBought) AS TotalPurchases
FROM dbo.tblProductPurchase AS p
GROUP BY p.ProductID
), ProductOrderCount AS (
SELECT
o.ProductID,
SUM(o.QtySold) AS TotalOrders
FROM dbo.tblProductOrder AS o
GROUP BY o.ProductID
)
SELECT
p.ProductID,
IIF(ISNULL(pc.TotalPurchases, 0) > ISNULL(oc.TotalOrders, 0), pc.TotalPurchases, oc.TotalOrders) AS ProductTransactionCount
FROM dbo.tblProduct AS p
LEFT JOIN ProductPurchaseCount AS pc
ON p.ProductID = pc.ProductID
LEFT JOIN ProductOrderCount AS oc
ON p.ProductID = oc.ProductID
WHERE NOT (pc.TotalPurchases IS NULL AND oc.TotalOrders IS NULL);

Apa yang kami lakukan di sini adalah kami membagi menjadi 3 langkah logis:

a) dapatkan SUM() dari jumlah yang dibeli oleh produk
b) dapatkan SUM() dari jumlah yang dipesan oleh produk

Karena kami tidak tahu apakah kami mungkin memiliki produk yang mungkin memiliki beberapa pembelian tetapi tidak ada pesanan atau produk yang memiliki pesanan tetapi tidak ada yang dibeli, kami tidak dapat meninggalkan kedua tabel tersebut. Oleh karena itu, kami menggunakan tabel produk sebagai sumber otoritatif dari semua ProductID yang ingin kami ketahui, yang membawa kami ke langkah ke-3:

c) mencocokkan jumlah dengan produk mereka, menentukan apakah produk memiliki transaksi (misalnya pembelian atau pesanan yang pernah dilakukan) dan jika demikian, pilih jumlah pasangan yang lebih tinggi. Itu adalah hitungan total transaksi kami yang telah dimiliki suatu produk.

Tetapi mengapa transaksi dihitung?

Tujuannya di sini adalah untuk mengetahui berapa banyak baris yang perlu kita hasilkan per produk untuk secara memadai mewakili setiap unit produk yang telah berpartisipasi dalam pembelian atau pesanan. Ingat dalam contoh ideal pertama kami, kami memiliki 3 pembelian dan 6 pesanan, keduanya seimbang dengan total 17 unit produk yang dibeli kemudian dipesan. Untuk produk tertentu, kita harus dapat membuat 17 baris untuk menghasilkan data yang kita miliki pada gambar di atas.

Jadi bagaimana kita mengubah nilai tunggal 17 berturut-turut menjadi 17 baris? Di situlah keajaiban tabel penghitungan masuk.

Jika Anda belum pernah mendengar tentang tabel penghitungan, Anda harus melakukannya sekarang. Saya akan membiarkan orang lain mengisi Anda dalam subjek tabel penghitungan; di sini, di sini dan di sini. Cukuplah untuk mengatakan, ini adalah alat yang hebat untuk dimiliki dalam toolkit SQL Anda.

Dengan asumsi kita merevisi kueri di atas sehingga bagian terakhir sekarang menjadi CTE bernama ProductTransactionCount, kita dapat menulis kueri sebagai berikut:
<the 3 CTEs from previous exampe>
INSERT INTO tblProductTransactionStaging (
ProductID,
TransactionNumber
)
SELECT
c.ProductID,
t.Num AS TransactionNumber
FROM ProductTransactionCount AS c
INNER JOIN dbo.tblTally AS t
ON c.TransactionCount >= t.Num;

Dan pesto! Kami sekarang memiliki baris sebanyak yang kami perlukan — tepatnya — untuk setiap produk yang perlu kami lakukan akuntansi. Perhatikan ekspresi dalam klausa ON – kita melakukan penggabungan segitiga – kita tidak menggunakan operator persamaan yang biasa karena kita ingin menghasilkan 17 baris dari udara tipis. Perhatikan bahwa hal yang sama dapat dicapai dengan klausa CROSS JOIN dan WHERE. Bereksperimenlah dengan keduanya untuk menemukan mana yang bekerja lebih baik.

Membuat transaksi kami diperhitungkan

Jadi kami memiliki tabel sementara kami mengatur jumlah baris yang tepat. Sekarang, kita perlu mengisi tabel dengan data tentang pembelian dan pesanan. Seperti yang Anda lihat pada gambar, kita harus dapat memesan pembelian dan pesanan masing-masing pada tanggal pembelian atau pemesanan. Dan di situlah ROW_NUMBER() dan tabel penghitungan datang untuk menyelamatkan.
SELECT
p.ProductID,
ROW_NUMBER() OVER (PARTITION BY p.ProductID ORDER BY p.PurchaseDate, p.PurchaseID) AS TransactionNumber,
p.PurchaseDate,
p.CostPer
FROM dbo.tblProductPurchase AS p
INNER JOIN dbo.tblTally AS t
ON p.QtyBought >= t.Num;

Anda mungkin bertanya-tanya mengapa kita membutuhkan ROW_NUMBER() ketika kita bisa menggunakan kolom Angka penghitungan. Jawabannya adalah jika ada beberapa pembelian, Num hanya akan setinggi jumlah pembelian itu tetapi kita harus mencapai 17 — total 3 pembelian terpisah dari 3, 6 dan 8 unit. Dengan demikian, kita mempartisi berdasarkan ProductID sedangkan Tally’s Num bisa dikatakan dipartisi oleh PurchaseID yang tidak kita inginkan.

Jika Anda menjalankan SQL, Anda sekarang akan mendapatkan breakout yang bagus, baris yang dikembalikan untuk setiap unit produk yang dibeli, dipesan berdasarkan tanggal pembelian. Perhatikan bahwa kami juga mengurutkan berdasarkan PurchaseID, untuk menangani kasus di mana ada beberapa pembelian produk yang sama pada hari yang sama sehingga kami harus memutuskan hubungan untuk memastikan bahwa angka Per-Biaya dihitung secara konsisten. Kami kemudian dapat memperbarui tabel sementara dengan pembelian:
WITH PurchaseData AS (
<previous query>
)
MERGE INTO dbo.tblProductTransactionStaging AS t
USING PurchaseData AS p
ON t.ProductID = p.ProductID
AND t.TransactionNumber = p.TransactionNumber
WHEN MATCHED THEN UPDATE SET
t.PurchaseID = p.PurchaseID,
t.PurchaseDate = p.PurchaseDate,
t.CostPer = p.CostPer;

Bagian pesanan pada dasarnya adalah hal yang sama – cukup ganti “Pembelian” dengan “Pesanan”, dan Anda akan mendapatkan tabel terisi seperti yang kami miliki pada gambar asli di awal posting.

Dan pada titik ini, Anda siap untuk melakukan semua jenis kebaikan akuntansi lainnya sekarang setelah Anda memecah produk dari tingkat transaksi ke tingkat unit yang Anda butuhkan untuk secara akurat memetakan biaya barang ke pendapatan. untuk unit produk tertentu menggunakan FIFO atau LIFO seperti yang dipersyaratkan oleh akuntan Anda. Perhitungannya sekarang dasar.

Perincian di dunia OLTP

Konsep granularity adalah konsep yang lebih umum di gudang data daripada di aplikasi OLTP tapi saya pikir skenario yang dibahas menyoroti kebutuhan untuk mundur dan mengidentifikasi dengan jelas apa granularity skema OLTP saat ini. Seperti yang kami lihat, kami memiliki perincian yang salah di awal dan kami perlu mengerjakan ulang sehingga kami bisa mendapatkan perincian yang diperlukan untuk mencapai pelaporan kami. Itu adalah kebetulan yang menyenangkan bahwa dalam kasus ini, kami dapat secara akurat menurunkan granularitas karena kami telah memiliki semua data komponen yang ada sehingga kami hanya perlu mengubah data. Itu tidak selalu terjadi, dan kemungkinan besar jika skema tidak cukup terperinci, itu akan memerlukan desain ulang skema. Meskipun demikian, mengidentifikasi perincian yang diperlukan untuk memenuhi persyaratan membantu dengan jelas menentukan langkah logis yang harus Anda lakukan untuk mencapai tujuan tersebut.

Lengkapi skrip SQL untuk mendemonstrasikan intinya bisa didapatkan DemoLowGranularity.sql.


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Parameter String Koneksi untuk Sumber Data Excel

  2. Bagaimana melakukan Gabungan Surat di Access 2016

  3. Bagaimana Access berbicara dengan sumber data ODBC? Bagian 3

  4. Merancang Pemicu Microsoft T-SQL

  5. Bagaimana Access berbicara dengan sumber data ODBC? Bagian 5