Sql-Server

使用另一個表中的隨機外鍵更新表中的所有行

  • January 24, 2018

我有四張桌子:(如下圖所示)

  • 主題白柱:

    • ID

      • 首要的關鍵
      • 整數
    • 類別ID

      • 對錶類別的引用
      • 整數
    • 使用者身份

      • 對錶使用者的引用
      • nvarchar(128)
  • 具有列的使用者:

    • ID

      • 首要的關鍵
      • nvarchar(128)
  • 類別白欄

    • ID

      • 首要的關鍵
      • 整數
  • UserCategoryLink 與列

    • 使用者身份

      • 首要的關鍵
      • 對錶使用者的引用
      • nvarchar(128)
    • 類別ID

      • 首要的關鍵
      • 對錶類別的引用
      • 整數

我將更新表主題,以便 CategoryID 是表 UserCategoryLink 的 CategoryID 之一。

**PS:**我使用 MS SQL Server。


**第3次更新:*就像您在這個SQL Fiddle上看到的那樣,每個使用者的主題表單中的類別不包含在表 UserCategoryLink 中,但它必須包含!所以馬克只能有自行車和滑雪的主題,而不是摩托車和游泳。現在,我將從表 UserCategoryLink 中的 CategoryID 列中將所有錯誤的(也可以更新的)*行更新為一個 ID。


**第一次更新:**我嘗試了以下程式碼

;WITH rs AS 
(
   SELECT UserID as Sid, CategoryID as Cid
   FROM UserCategorieLink
)
update Topic 
   set CategoryID = (select top 1 Cid from rs where UserID = Sid) 
   where UserID = (select top 1 Sid from rs where UserID = Sid);

但結果並不是每個使用者最喜歡的類別隨機選擇的。我知道它來自,top 1但這是因為我不知道如何生成隨機數。

我將從 select 語句中獲取隨機行*(參見下面的程式碼/就像我可以在 C# 等程式語言中做的那樣)*,但它給了我一個錯誤,因為RAND生成了一個介於 0 和 1 之間的隨機數。

RAND(select top 1 Cid from rs where UserID = Sid)

錯誤是:

關鍵字“select”附近的語法不正確

‘)’ 附近的語法不正確。

在第 7行。


**第 2 次更新:**程式碼還為來自同一使用者的每個主題提供了相同的隨機數。那也可以是隨機數嗎?我知道每個使用者總是有兩個最喜歡的類別。查詢必須選擇其中之一。

我知道它來自where更新語句的子句。但是我該如何解決呢?

不會完成您要完成的工作,但對於您的更新,您使用的是TOP沒有ORDER BY. 雖然 SQL Server 不保證此類查詢的順序,但它也不只是隨機選擇。如果要強制返回隨機行,則需要按行級隨機數排序。為此,您可以使用ORDER BY ABS( CHECKSUM( NEWID() ) ).

試一試sys.objects以查看顯式隨機排序的行為。

SELECT  TOP 1 name
FROM    sys.objects
ORDER BY ABS( CHECKSUM( NEWID() ) );

不管你在做什麼,祝你好運。

編輯:

@jean 在評論NEWID()中指出,這就是所有必要的,這是 100% 正確的,我只是肌肉記憶,ABS( CHECKSUM() )因為我傾向於使用操作員進行行級隨機化%

編輯2:

那麼這樣的事情呢?

UPDATE  t
   SET CategoryID = nt.CategoryID
FROM    dbo.Topic t
INNER JOIN (    SELECT  t.ID, ucl.CategoryID, 
                       Ordinal = ROW_NUMBER() OVER (
                           PARTITION BY t.ID
                           ORDER BY NEWID() )
               FROM    dbo.Topic t
               INNER JOIN dbo.UserCategoryLink ucl
                   ON  t.UserID = ucl.UserID ) nt
   ON  t.ID = nt.ID
WHERE   nt.Ordinal = 1;

引用自:https://dba.stackexchange.com/questions/120739