Dalam mendapat tugas pemrograman di bidang T-SQL
.
Tugas:
- Orang ingin masuk ke dalam lift setiap orang memiliki berat tertentu.
- Urutan orang-orang yang mengantri ditentukan oleh giliran kolom.
- Lift memiliki kapasitas maksimal <= 1000 lbs.
- Kembalikan nama orang terakhir yang bisa masuk lift sebelum terlalu berat!
- Jenis pengembalian harus berupa tabel
Pertanyaan: Apa cara paling efisien untuk menyelesaikan masalah ini? Jika perulangan benar, apakah ada ruang untuk perbaikan?
Saya menggunakan loop dan tabel # temp, di sini solusi saya:
set rowcount 0
-- THE SOURCE TABLE "LINE" HAS THE SAME SCHEMA AS #RESULT AND #TEMP
use Northwind
go
declare @sum int
declare @curr int
set @sum = 0
declare @id int
IF OBJECT_ID('tempdb..#temp','u') IS NOT NULL
DROP TABLE #temp
IF OBJECT_ID('tempdb..#result','u') IS NOT NULL
DROP TABLE #result
create table #result(
id int not null,
[name] varchar(255) not null,
weight int not null,
turn int not null
)
create table #temp(
id int not null,
[name] varchar(255) not null,
weight int not null,
turn int not null
)
INSERT into #temp SELECT * FROM line order by turn
WHILE EXISTS (SELECT 1 FROM #temp)
BEGIN
-- Get the top record
SELECT TOP 1 @curr = r.weight FROM #temp r order by turn
SELECT TOP 1 @id = r.id FROM #temp r order by turn
--print @curr
print @sum
IF(@sum + @curr <= 1000)
BEGIN
print 'entering........ again'
--print @curr
set @sum = @sum + @curr
--print @sum
INSERT INTO #result SELECT * FROM #temp where [id] = @id --id, [name], turn
DELETE FROM #temp WHERE id = @id
END
ELSE
BEGIN
print 'breaaaking.-----'
BREAK
END
END
SELECT TOP 1 [name] FROM #result r order by r.turn desc
Di sini skrip Buat untuk tabel yang saya gunakan Northwind untuk pengujian:
USE [Northwind]
GO
/****** Object: Table [dbo].[line] Script Date: 28.05.2018 21:56:18 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[line](
[id] [int] NOT NULL,
[name] [varchar](255) NOT NULL,
[weight] [int] NOT NULL,
[turn] [int] NOT NULL,
PRIMARY KEY CLUSTERED
(
[id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY],
UNIQUE NONCLUSTERED
(
[turn] 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
ALTER TABLE [dbo].[line] WITH CHECK ADD CHECK (([weight]>(0)))
GO
INSERT INTO [dbo].[line]
([id], [name], [weight], [turn])
VALUES
(5, 'gary', 800, 1),
(3, 'jo', 350, 2),
(6, 'thomas', 400, 3),
(2, 'will', 200, 4),
(4, 'mark', 175, 5),
(1, 'james', 100, 6)
;
sumber
Client statistics --> Total Execution Time
, bukanActual execution plan
yang mungkin paling menarik di sini. SebagaiClient Statistics
solusi Anda sedikit lebih lambat maka Martin. Terima kasih atas info tambahannya. Metode mana yang dapat digunakan untuk mengukur perbedaan kinerja antara berbagai pendekatan?ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW
memperkenalkanSequence Project (Compute Scalar)
, operator. Tidak perlu dikatakan saya tidak tahu apa artinya ini :-)Anda bisa melakukan join sendiri:
Hal semacam ini tidak terlalu efisien karena menyebabkan pilih per baris. Tapi setidaknya itu dinyatakan sebagai satu pernyataan.
Jika Anda tidak harus melakukannya sepenuhnya dalam SQL maka Anda dapat dengan mudah memilih semua baris dan mengulanginya, menambahkan saat Anda pergi.
Anda bisa melakukan hal yang sama dalam prosedur tersimpan tanpa tabel temp juga. Cukup tahan jumlah dan nama baris terakhir dalam sebuah variabel.
sumber
self-join
, jika Anda bisa membuat contoh kecil yang dapat direproduksi, saya telah menambahkan definisi tabel ke pertanyaan saya. Sql saya jelek .... Saya perlu nama orang yang paling dekat dengan <= 1000 lbs.COALESCE()
atauISNULL()
fungsi atauCASE
ekspresi untuk membuatnya 0.