এলোমেলো সংখ্যা এবং যোগদানের প্রকারের সাথে অপ্রত্যাশিত ফলাফল


16

আমার কাছে একটি সাধারণ স্ক্রিপ্ট রয়েছে যা চারটি এলোমেলো সংখ্যা পেয়ে থাকে (1 থেকে 4 এর মধ্যে) এবং তারপরে ম্যাচিং ডাটাবেস_আইডি নম্বর পেতে ফিরে যোগ দেয়। যখন আমি স্ক্রিপ্টটি একটি বাম যোগদানের সাথে চালাই, আমি প্রতিবার চারটি সারি ফিরে পাই (প্রত্যাশিত ফলাফল)। যাইহোক, আমি যখন এটি একটি অন্তর্ভুক্ত যোগদান দিয়ে চালিত করি, তখন আমি বিভিন্ন ধরণের সারি পাই - কখনও কখনও দুটি, কখনও কখনও আট eight

যৌক্তিকভাবে, কোনও পার্থক্য হওয়া উচিত না কারণ আমি জানি যে ডাটাবেস_আইডস 1-4 সহ সারিগুলি সিস.ড্যাটাবেসগুলিতে বিদ্যমান। এবং যেহেতু আমরা চারটি সারি (এটিতে যোগদানের বিপরীতে) দিয়ে এলোমেলো নম্বর টেবিলটি থেকে নির্বাচন করছি, সেখানে আর কখনও কখনও চারটি সারি আর ফিরে আসবে না।

এটি এসকিউএল সার্ভার ২০১২ এবং 2014 উভয় ক্ষেত্রেই ঘটে happens অভ্যন্তরীণ যোগদানের ফলে কীভাবে বিভিন্ন সংখ্যক সারি ফিরে আসে?

/* Works as expected -- always four rows */

SELECT rando.RandomNumber, d.database_id
FROM 
  (SELECT 1 + ABS(CHECKSUM(NEWID())) % (4) AS RandomNumber 
   FROM sys.databases WHERE database_id <= 4) AS rando
LEFT JOIN sys.databases d ON rando.RandomNumber = d.database_id;


/* Returns a varying number of rows */

SELECT rando.RandomNumber, d.database_id
FROM 
  (SELECT 1 + ABS(CHECKSUM(NEWID())) % (4) AS RandomNumber 
   FROM sys.databases WHERE database_id <= 4) AS rando
INNER JOIN sys.databases d ON rando.RandomNumber = d.database_id;

/* Also returns a varying number of rows */

WITH rando AS (
  SELECT 1 + ABS(CHECKSUM(NEWID())) % (4) AS RandomNumber
  FROM sys.databases WHERE database_id <= 4
)

SELECT r.RandomNumber, d.database_id
FROM rando AS r
INNER JOIN sys.databases d ON r.RandomNumber = d.database_id;

3
সর্বদা 4 টি সারি পাওয়ার আরেকটি উপায়: SELECT TOP (4) d.database_id FROM sys.databases AS d CROSS JOIN (VALUES (1),(2),(3),(4)) AS multi (i) WHERE d.database_id <= 4 ORDER BY CHECKSUM(NEWID()) ;আমি অনুমান করি যে এটি ঠিকঠাক কাজ করে কারণ অ-নিরোধক ক্রিয়াকলাপের মানটিতে কোনও যোগসূত্র নেই।
ypercubeᵀᴹ

উত্তর:


9

অতিরিক্ত নির্বাচিত যোগ করার মাধ্যমে এটি পরিকল্পনার আরও নিচে গণনা স্কেলারের মূল্যায়ন ঠেলে দেয় এবং জোড়টিকে প্রাকটিকেট দেয়, উপরের অংশে কম্পিউট স্কেলারটি তারপরে আগেরটির উল্লেখ করে।

SELECT rando.RandomNumber, d.database_id
FROM 
  (SELECT ( SELECT 1 + ABS(CHECKSUM(NEWID())) % (4)) AS RandomNumber 
   FROM sys.databases WHERE database_id <= 4) AS rando
INNER JOIN sys.databases d ON rando.RandomNumber = d.database_id

|--Compute Scalar(DEFINE:([Expr1071]=[Expr1070]))

|--Compute Scalar(DEFINE:([Expr1070]=(1)+abs(checksum(newid()))%(4)))

এখনও এটি কেন এত দেরি করে তা খনন করা হচ্ছে তবে বর্তমানে পল হোয়াইটের এই পোস্টটি পড়ছেন ( https://sql.kiwi/2012/09/compute-scalars-expressions-and-execution-plan-performance.html ) । নিউআইডিড নির্বিচারবাদী নয় এই সত্যটির সাথে সম্ভবত এর কিছু যুক্তি রয়েছে?


12

এটি সাইট চিমসে চতুর লোকদের মধ্যে অবধি অবধি অন্তর্দৃষ্টি দিতে পারে।

আমি এলোমেলো ফলাফলগুলি একটি অস্থায়ী টেবিলের মধ্যে রেখেছি এবং যোগদানের ধরণ নির্বিশেষে আমি ধারাবাহিকভাবে 4 ফলাফল পেয়েছি।

/* Works as expected -- always four rows */

DECLARE @Rando table
(
    RandomNumber int
);

INSERT INTO
    @Rando
(
    RandomNumber
)
-- This generates 4 random numbers from 1 to 4, endpoints inclusive
SELECT
    1 + ABS(CHECKSUM(NEWID())) % (4) AS RandomNumber
FROM
    sys.databases
WHERE
    database_id <= 4;

SELECT
    *
FROM
    @Rando AS R;

SELECT
    rando.RandomNumber
,   d.database_id
FROM 
    @Rando AS rando
    LEFT JOIN 
        sys.databases d 
        ON rando.RandomNumber = d.database_id
ORDER BY 1,2;


/* Returns a varying number of rows */

SELECT rando.RandomNumber, d.database_id
FROM 
    @Rando AS rando
    INNER JOIN 
        sys.databases d 
        ON rando.RandomNumber = d.database_id
ORDER BY 1,2;

/* Also returns a varying number of rows */

WITH rando AS 
(
    SELECT * FROM @Rando AS rando
)
SELECT r.RandomNumber, d.database_id
FROM 
    rando AS r
    INNER JOIN 
        sys.databases d 
        ON r.RandomNumber = d.database_id
ORDER BY 1,2;

যদি আমি আপনার দ্বিতীয় ক্যোয়ারী এবং একটি টেবিল ভেরিয়েবলের সাথে তারতম্যের মধ্যে ক্যোয়ারী পরিকল্পনাগুলি তুলনা করি তবে আমি দেখতে পাচ্ছি যে দুটির মধ্যে একটি নির্দিষ্ট পার্থক্য রয়েছে। রেড এক্সটি No Join Predicateতাই আমার ক্যাভম্যান বিকাশকারী মস্তিষ্কের কাছে সত্যিই অদ্ভুত বলে মনে হয়

এখানে চিত্র বর্ণনা লিখুন

যদি আমি কোয়েরির এলোমেলো বিটটিকে একটি ধ্রুবক থেকে মুছে 1 % (4)ফেলি তবে আমার পরিকল্পনাটি আরও ভাল দেখায় তবে কমপিউট স্কেলারটি মুছে ফেলা হয়েছিল যাতে আমাকে আরও কাছের দিকে নিয়ে যেতে পরিচালিত করে

এখানে চিত্র বর্ণনা লিখুন

এটি যোগদানের পরে এলোমেলো সংখ্যার জন্য অভিব্যক্তিটি কম্পিউটিং করছে। এটি প্রত্যাশিত হোক না কেন, আমি এখনও সাইটে অভ্যন্তরীণ উইজার্ডগুলিতে চলে যাই তবে কমপক্ষে সে কারণেই আপনি নিজের যোগদানের ক্ষেত্রে পরিবর্তনশীল ফলাফল পাচ্ছেন।

2014

ঘরে বসে যারা খেলছেন তাদের জন্য, উপরের ক্যোয়ারী পরিকল্পনাগুলি ২০০৮ এর আর ২ উদাহরণ থেকে উত্পন্ন হয়েছিল। 2014 এর পরিকল্পনাগুলি দেখতে অন্যরকম দেখায় তবে যোগদানের পরে কমপ্যুট স্কেলার অপারেশনটি রয়ে গেছে।

ধ্রুবক অভিব্যক্তিটি ব্যবহার করে এটি 2014 এর কোয়েরি পরিকল্পনা

এখানে চিত্র বর্ণনা লিখুন

এটি নতুন আইডির এক্সপ্রেশনটি ব্যবহার করে 2014 উদাহরণের জন্য ক্যোয়ারী পরিকল্পনা।

এখানে চিত্র বর্ণনা লিখুন

এটি দৃশ্যত ডিজাইনের মাধ্যমে, এখানে সংযুক্ত ইস্যু । অস্তিত্বের বিষয়টি জানার জন্য @ পলওহাইটকে ধন্যবাদ জানাই।


1
ঠিক, ঠিক - যা ঘটছে, তবে এটি অবশ্যই প্রত্যাশিত নয়। ফলাফলটি যে টি-এসকিউএল পাশ করা হচ্ছে তার সাথে মেলে না, এবং এইভাবে প্রশ্নের।
ব্রেন্ট ওজার

এমনকি এলোমেলো সংখ্যার স্থিতিশীল 1 দিয়ে প্রতিস্থাপন করলে জোয়ার অপারেটরটিকে কোনও
জেমস অ্যান্ডারসন

দেখে মনে হচ্ছে আপনি কিছু করছেন to এমনকি অপশন (ফরেক্স অর্ডার) ব্যবহার করেও আচরণটি পরিবর্তন হয় না - এলোমেলো সংখ্যাটি এখনও শেষ হিসাবে গণনা করা হয় ...
যিরমিয় পেশকা

সিএস.ড্যাটাবেসগুলি টিভিএফ মুছে ফেলা, নিম্নলিখিতগুলি একই পরিকল্পনাটি তৈরি করে: gist.github.com/peschkaj/cebdeb98daa4d1f08dc5
যেরেমিয় পেশকা

এটি অপারেটর অগ্রাধিকার ইস্যুর মতো শোনাচ্ছে
জেমস অ্যান্ডারসন
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.