[英]How to get value greater than multiple columns value rather than using composite key field from SQL Server
如果我有包含以下數據的表:
分支,類型,數字=>這將生成復合鍵字符串'keyfield'
分支的長度,類型為[int] [4]
數字的長度為[int] [7]
數據是這樣的:
branch, type, number
13, 1309, 1 row1
13, 1309, 2 row2
13, 1310, 1 row3
14, 1309, 1 row4
所以我有keyfield->稱為'KeyField'列,但是idont需要使用它,它可以工作,但是我只需要使用表達式而不是字符串keyfield例如:
如果我需要使行大於上面的row2:我寫道:
SELECT TOP 1 * FROM TABLE WHERE KeyField > '0013130900002'
->我不喜歡使用字符串作為復合鍵..
我也不能像這樣手動進行:
SELECT TOP 1 * FROM TABLE WHERE brn > 1 AND type > 1309 and num > 2
它不起作用...所以我需要按表達式獲取下一行
例如:getGreatRow(1,1309,2); //這將返回row3我需要做的。 這樣該功能可以直接與C#和屏幕上的文本框一起使用! 我需要選擇唯一的前1條記錄,該記錄大於我指定的當前記錄或表達式的值。
編輯
我根據需要使用Gordon SQL生成帶有主鍵列表的C#。 感謝戈登。
在C#中使SQL查詢自動生成:
public List<EntryTable> Tables { get; private set; }
public List<BufferElement> Buffer { get; private set; }
string Query = string.Empty;
for (int i = 0; i < Tables[0].PrimaryKeys.Count; i++)
{
Query += "(";
for (int j = 0; j < i; j++)
{
switch (Tables[0].PrimaryKeys[j].CLRType)
{
case CLRType.CLR_BYTE:
Query += $"{Tables[0].PrimaryKeys[j].KeyPart} = {Convert.ToByte(Buffer.Find(x => x.ID == Tables[0].PrimaryKeys[j].KeyPart).Value)} AND ";
break;
case CLRType.CLR_INT16:
Query += $"{Tables[0].PrimaryKeys[j].KeyPart} = {Convert.ToInt16(Buffer.Find(x => x.ID == Tables[0].PrimaryKeys[j].KeyPart).Value)} AND ";
break;
case CLRType.CLR_INT32:
Query += $"{Tables[0].PrimaryKeys[j].KeyPart} = {Convert.ToInt32(Buffer.Find(x => x.ID == Tables[0].PrimaryKeys[j].KeyPart).Value)} AND ";
break;
case CLRType.CLR_INT64:
Query += $"{Tables[0].PrimaryKeys[j].KeyPart} = {Convert.ToInt64(Buffer.Find(x => x.ID == Tables[0].PrimaryKeys[j].KeyPart).Value)} AND ";
break;
case CLRType.CLR_SINGLE:
Query += $"{Tables[0].PrimaryKeys[j].KeyPart} = {Convert.ToSingle(Buffer.Find(x => x.ID == Tables[0].PrimaryKeys[j].KeyPart).Value)} AND ";
break;
case CLRType.CLR_DOUBLE:
Query += $"{Tables[0].PrimaryKeys[j].KeyPart} = {Convert.ToDouble(Buffer.Find(x => x.ID == Tables[0].PrimaryKeys[j].KeyPart).Value)} AND ";
break;
case CLRType.CLR_DECIMAL:
Query += $"{Tables[0].PrimaryKeys[j].KeyPart} = {Convert.ToDecimal(Buffer.Find(x => x.ID == Tables[0].PrimaryKeys[j].KeyPart).Value)} AND ";
break;
case CLRType.CLR_Boolean:
Query += $"{Tables[0].PrimaryKeys[j].KeyPart} = {Convert.ToBoolean(Buffer.Find(x => x.ID == Tables[0].PrimaryKeys[j].KeyPart).Value)} AND ";
break;
case CLRType.CLR_STRING:
Query += $"{Tables[0].PrimaryKeys[j].KeyPart} = '{Convert.ToString(Buffer.Find(x => x.ID == Tables[0].PrimaryKeys[j].KeyPart).Value)}' AND ";
break;
case CLRType.CLR_DATETIME:
Query += $"{Tables[0].PrimaryKeys[j].KeyPart} = '{Convert.ToDateTime(Buffer.Find(x => x.ID == Tables[0].PrimaryKeys[j].KeyPart).Value)}' AND ";
break;
case CLRType.CLR_TIME:
Query += $"{Tables[0].PrimaryKeys[j].KeyPart} = '{TimeSpan.Parse(Buffer.Find(x => x.ID == Tables[0].PrimaryKeys[j].KeyPart).Value)}' AND ";
break;
}
}
switch (Tables[0].PrimaryKeys[i].CLRType)
{
case CLRType.CLR_BYTE:
Query += $"{Tables[0].PrimaryKeys[i].KeyPart} > {Convert.ToByte(Buffer.Find(x => x.ID == Tables[0].PrimaryKeys[i].KeyPart).Value)}";
break;
case CLRType.CLR_INT16:
Query += $"{Tables[0].PrimaryKeys[i].KeyPart} > {Convert.ToInt16(Buffer.Find(x => x.ID == Tables[0].PrimaryKeys[i].KeyPart).Value)}";
break;
case CLRType.CLR_INT32:
Query += $"{Tables[0].PrimaryKeys[i].KeyPart} > {Convert.ToInt32(Buffer.Find(x => x.ID == Tables[0].PrimaryKeys[i].KeyPart).Value)}";
break;
case CLRType.CLR_INT64:
Query += $"{Tables[0].PrimaryKeys[i].KeyPart} > {Convert.ToInt64(Buffer.Find(x => x.ID == Tables[0].PrimaryKeys[i].KeyPart).Value)}";
break;
case CLRType.CLR_SINGLE:
Query += $"{Tables[0].PrimaryKeys[i].KeyPart} > {Convert.ToSingle(Buffer.Find(x => x.ID == Tables[0].PrimaryKeys[i].KeyPart).Value)}";
break;
case CLRType.CLR_DOUBLE:
Query += $"{Tables[0].PrimaryKeys[i].KeyPart} > {Convert.ToDouble(Buffer.Find(x => x.ID == Tables[0].PrimaryKeys[i].KeyPart).Value)}";
break;
case CLRType.CLR_DECIMAL:
Query += $"{Tables[0].PrimaryKeys[i].KeyPart} > {Convert.ToDecimal(Buffer.Find(x => x.ID == Tables[0].PrimaryKeys[i].KeyPart).Value)}";
break;
case CLRType.CLR_Boolean:
Query += $"{Tables[0].PrimaryKeys[i].KeyPart} > {Convert.ToBoolean(Buffer.Find(x => x.ID == Tables[0].PrimaryKeys[i].KeyPart).Value)}";
break;
case CLRType.CLR_STRING:
Query += $"{Tables[0].PrimaryKeys[i].KeyPart} > '{Convert.ToString(Buffer.Find(x => x.ID == Tables[0].PrimaryKeys[i].KeyPart).Value)}'";
break;
case CLRType.CLR_DATETIME:
Query += $"{Tables[0].PrimaryKeys[i].KeyPart} > '{Convert.ToDateTime(Buffer.Find(x => x.ID == Tables[0].PrimaryKeys[i].KeyPart).Value)}'";
break;
case CLRType.CLR_TIME:
Query += $"{Tables[0].PrimaryKeys[i].KeyPart} > '{TimeSpan.Parse(Buffer.Find(x => x.ID == Tables[0].PrimaryKeys[i].KeyPart).Value)}'";
break;
}
Query += $") {(Tables[0].PrimaryKeys.Count > 1 && i != Tables[0].PrimaryKeys.Count - 1 ? " OR " : string.Empty)} \n";
}
Query += $"ORDER BY {string.Join(" ASC, ", Tables[0].PrimaryKeys.Select(x => x.KeyPart).ToArray())} ASC";
SelectCommand = $"SELECT TOP 1 * FROM {Tables[0].Table} WHERE " + Query;
如果您嘗試獲取1, 1309, 2
之后的下一行
SELECT TOP 1 *
FROM TABLE
WHERE brn > 1 OR
(brn = 1 AND type > 1309) OR
(brn = 1 AND type = 1309 AND num > 2)
ORDER BY brn DESC, type DESC, num DESC;
我建議您使用“數學”:將列按“相關順序”放置,然后相乘以在單個字段中容納所有數字。 例如: new_id=first_column*100000+second_column*10+third_column
因此,在第1行的情況下,您將獲得1313091作為代碼。 數學比字符串處理要快得多。 然后,您將能夠查詢將密鑰除以所需的部分。 最終向您認為會增加很多的列添加更多零。
當您使用列構建鍵時,將保留順序,以便您需要外部鍵。
因此您的查詢將類似於:
select *
from table
where new_id > (branch)*100000+(type)*10+number
IDEA是這樣的:
123456 99349199 12341234 : having enough space for a 'reasonable' amount of numbers
000000 00000000 00000000
so 123456 x 1 00000000 00000000 = 123456 00000000 00000000 +
99349199 x 1 00000000 = 99349199 00000000 +
and
12341234 x 1 = 12341234 =
-------------------------
123456 99349199 12341234
更新:
select *
from my_table
WHERE new_id (branch)*1 00000000 00000000+(type)*1 00000000+number
顯然,我們的“ new_label”定義已更改:
new_label= (branch)*100000000 00000000+(type)*100000000 + number
因此您可以擁有以下最大長度:
<all digits you want> (branch) + 8 digit (type) + 8 digit (number)
我建議您添加數據庫觸發器以強制執行這些最大長度
在數據庫中創建此功能
CREATE FUNCTION dbo.GetCompositeKey(@branch int, @type int, @number int)
RETURNS bigint
AS
BEGIN
RETURN cast(@branch as bigint) * 100000000000 + cast(@type as bigint) * 10000000 + @number
END
然后在比較時使用它,如下所示:
SELECT TOP 1 * FROM [TABLE]
WHERE dbo.GetCompositeKey(branch, type, number) >
dbo.GetCompositeKey(13, 1309, 2)
ORDER BY dbo.GetCompositeKey(branch, type, number)
注意:此查詢已簡化,以用於說明。 從C#執行時,應使用參數化查詢為SQL函數提供3個整數,以避免SQL注入攻擊。
編輯:發布此內容后,我讀了一些其他答案的評論,其中您說您不懂數學。 到目前為止,在大多數答案中,方法只是創建一個將所有三個值(分支,類型和數字)組合在一起以創建可比較值的大整數。 實際上,這與在您的問題('0013130900002')中使用字符串連接和基於字符串的復合鍵的操作相同。 正如另一個答案中指出的那樣,數學方法應該更快。 字符串中的另一個錯誤是將@number字段僅零填充為5位數字,當您已經聲明它必須能夠容納7位數字時。
到目前為止,所有答案都使用非常基礎的數學。 如果您不懂基本的數學知識,您將無法像一名程序員那樣步履維艱,因此您應該優先考慮提高該技能。
您在對其他答案的評論中說過,您不想填充DataSet或使用MoveNext等。另一種方法是創建一個包含復合鍵的視圖。
首先,創建我在其他答案中定義的函數
然后,創建視圖
CREATE VIEW [myview]
AS
SELECT
*,
dbo.GetCompositeKey(branch, type, number) as CompositeKey
FROM [table]
像這樣查詢它:
SELECT TOP 1 * FROM [myview]
WHERE CompositeKey > dbo.GetCompositeKey(13, 1309, 2)
ORDER BY CompositeKey
這種方法可能會比我的其他答案提高查詢性能。 您需要對其進行測試才能找到答案。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.