অ্যাক্সেস (জেট) এসকিউএল: টেবিলবিতে ডেটটাইম স্ট্যাম্পগুলি টেবিলএতে প্রতিটি ডেটটাইম স্ট্যাম্পকে ফ্ল্যাঙ্ক করে


21

প্রথম শব্দ

আপনি JOIN গুলি নীচে (এবং সহ) বিভাগগুলি নিরাপদে উপেক্ষা করতে পারেন: আপনি কেবল কোডটির ক্র্যাক নিতে চাইলে শুরু শুরু if পটভূমি এবং ফলাফল মাত্র প্রসঙ্গ হিসাবে পরিবেশন করা। আপনি যদি প্রাথমিকভাবে কোডটি দেখতে কেমন দেখতে চান তবে দয়া করে 2015-10-06 এর আগে সম্পাদনা ইতিহাস দেখুন।


উদ্দেশ্য

শেষ পর্যন্ত আমি টেবিলের মধ্যে উপলব্ধ জিপিএস ডেটার ডেটটাইম স্ট্যাম্পগুলির উপর ভিত্তি করে ট্রান্সমিটারের ( Xবা Xmit) ইন্টারপোলটেড জিপিএস স্থানাঙ্কগুলি গণনা করতে চাই যা টেবিলে SecondTableপর্যবেক্ষণটিকে সরাসরি ফ্ল্যাঙ্ক করে FirstTable

চূড়ান্ত উদ্দেশ্য অর্জনের জন্য আমার তাত্ক্ষণিক উদ্দেশ্য হ'ল সেই স্বল্প সময় পয়েন্টগুলি পেতে কীভাবে সেরা যোগদান FirstTableকরা যায় SecondTableতা নির্ধারণ করা। পরবর্তীতে আমি সেই তথ্যটি ব্যবহার করতে পারি মধ্যবর্তী জিপিএস স্থানাংকগুলি গণনা করতে পারি সমুদ্রের সমন্বয় ব্যবস্থা বরাবর রৈখিক ফিটিং ধরে রেখেছি (অভিনব শব্দ বলতে আমি এই বিষয়টিকে বিবেচনা করি না যে পৃথিবী এই স্কেলটিতে একটি গোলক)।


প্রশ্নাবলি

  1. টাইম স্ট্যাম্পগুলির আগে-পরে-নিকটস্থ সবচেয়ে বেশি কার্যকর উপায় আছে কি?
    • কেবল "পরে" দখল করে এবং তারপরে "পরে" সম্পর্কিত হিসাবে কেবল "আগে" পেয়ে আমার দ্বারা স্থির।
  2. আরও একটি স্বজ্ঞাত উপায় আছে যা (A<>B OR A=B)কাঠামোর সাথে জড়িত নয় ।
    • বায়ার্ডজি মৌলিক বিকল্পগুলি সরবরাহ করেছিলেন, তবে আমার "রিয়েল-ওয়ার্ল্ড" অভিজ্ঞতা তার 4 টি যোগদানের কৌশলগুলি একইভাবে সম্পাদন করে না। তবে বিকল্প যোগদানের শৈলীগুলিকে সম্বোধনের জন্য তার সম্পূর্ণ কৃতিত্ব।
  3. আপনার কাছে থাকতে পারে অন্য কোনও চিন্তা, কৌশল এবং পরামর্শ।
    • উভয় Thusfar byrdzeye এবং Phrancis এ ব্যাপারে বেশ সহায়ক হয়েছে। আমি দেখতে পেলাম যে ফ্রেঞ্চিসের পরামর্শটি চমৎকারভাবে নির্ধারণ করা হয়েছিল এবং একটি জটিল পর্যায়ে সহায়তা সরবরাহ করেছিল, তাই আমি তাকে এখানে প্রান্তটি দেব।

প্রশ্ন 3 সম্পর্কে আমি যে কোনও অতিরিক্ত সহায়তা পেতে পারি তার জন্য আমি তার কৃতজ্ঞতা প্রকাশ করব Bul


সারণী সংজ্ঞা

আধা ভিজ্যুয়াল উপস্থাপনা

FirstTable

Fields
  RecTStamp | DateTime  --can contain milliseconds via VBA code (see Ref 1) 
  ReceivID  | LONG
  XmitID    | TEXT(25)
Keys and Indices
  PK_DT     | Primary, Unique, No Null, Compound
    XmitID    | ASC
    RecTStamp | ASC
    ReceivID  | ASC
  UK_DRX    | Unique, No Null, Compound
    RecTStamp | ASC
    ReceivID  | ASC
    XmitID    | ASC

SecondTable

Fields
  X_ID      | LONG AUTONUMBER -- seeded after main table has been created and already sorted on the primary key
  XTStamp   | DateTime --will not contain partial seconds
  Latitude  | Double   --these are in decimal degrees, not degrees/minutes/seconds
  Longitude | Double   --this way straight decimal math can be performed
Keys and Indices
  PK_D      | Primary, Unique, No Null, Simple
    XTStamp   | ASC
  UIDX_ID   | Unique, No Null, Simple
    X_ID      | ASC

রিসিভারডেটেলস টেবিল

Fields
  ReceivID                      | LONG
  Receiver_Location_Description | TEXT -- NULL OK
  Beginning                     | DateTime --no partial seconds
  Ending                        | DateTime --no partial seconds
  Lat                           | DOUBLE
  Lon                           | DOUBLE
Keys and Indicies
  PK_RID  | Primary, Unique, No Null, Simple
    ReceivID | ASC

ValidXmitters সারণী

Field (and primary key)
  XmitID    | TEXT(25) -- primary, unique, no null, simple

এসকিউএল ফিডাল ...

... যাতে আপনি সারণী সংজ্ঞা এবং কোড দিয়ে খেলতে পারেন এই প্রশ্নটি এমএসএ্যাকসেসের জন্য, তবে ফ্রেঞ্চিস যেমন উল্লেখ করেছেন, অ্যাক্সেসের জন্য কোনও এসকিউএল ফ্রেডল স্টাইল নেই। সুতরাং, ফ্রেঞ্চিসের উত্তরের উপর ভিত্তি করে আমার সারণী সংজ্ঞা এবং কোড দেখতে আপনি এখানে যেতে সক্ষম হবেন : http://sqlfiddle.com/#!6/e9942/4 (বাহ্যিক লিঙ্ক)


যোগ দিন: শুরু হচ্ছে

আমার বর্তমান "অভ্যন্তরীণ সাহস" জয়েন কৌশল

প্রথমে কলাম অর্ডার এবং যৌগিক প্রাথমিক কী (RecTStamp, ReceivID, XmitID)সমস্ত সূচকযুক্ত / সাজানো হয়েছে এমন একটি ফার্স্ট টেবিল_প্রযুক্তি তৈরি করুন ASC। আমি পৃথকভাবে প্রতিটি কলামে সূচি তৈরি করেছি। তারপরে এটি পূরণ করুন।

INSERT INTO FirstTable_rekeyed (RecTStamp, ReceivID, XmitID)
  SELECT DISTINCT ROW RecTStamp, ReceivID, XmitID
  FROM FirstTable
  WHERE XmitID IN (SELECT XmitID from ValidXmitters)
  ORDER BY RecTStamp, ReceivID, XmitID;

উপরের জিজ্ঞাসাটি 153006 রেকর্ড সহ নতুন টেবিলটি পূরণ করে এবং 10 সেকেন্ড বা তার বেশি সময়ের মধ্যে ফিরে আসে।

নিম্নলিখিত 1 বা দুটি মধ্যে সম্পূর্ণ করা হয় যখন শীর্ষ 1 সাবকোরি পদ্ধতিটি ব্যবহৃত হয় যখন এই পুরো পদ্ধতিটি একটি "নির্বাচন গণনা (*) ফর্ম (...)" এ আবৃত থাকে

SELECT 
    ReceiverRecord.RecTStamp, 
    ReceiverRecord.ReceivID, 
    ReceiverRecord.XmitID,
    (SELECT TOP 1 XmitGPS.X_ID FROM SecondTable as XmitGPS WHERE ReceiverRecord.RecTStamp < XmitGPS.XTStamp ORDER BY XmitGPS.X_ID) AS AfterXmit_ID
    FROM FirstTable_rekeyed AS ReceiverRecord
    -- INNER JOIN SecondTable AS XmitGPS ON (ReceiverRecord.RecTStamp < XmitGPS.XTStamp)
         GROUP BY RecTStamp, ReceivID, XmitID;
-- No separate join needed for the Top 1 method, but it would be required for the other methods. 
-- Additionally no restriction of the returned set is needed if I create the _rekeyed table.
-- May not need GROUP BY either. Could try ORDER BY.
-- The three AfterXmit_ID alternatives below take longer than 3 minutes to complete (or do not ever complete).
  -- FIRST(XmitGPS.X_ID)
  -- MIN(XmitGPS.X_ID)
  -- MIN(SWITCH(XmitGPS.XTStamp > ReceiverRecord.RecTStamp, XmitGPS.X_ID, Null))

পূর্ববর্তী "অভ্যন্তর সাহস" JOIN ক্যোয়ারী

প্রথম (ফাস্টিশ ... তবে যথেষ্ট ভাল নয়)

SELECT 
  A.RecTStamp,
  A.ReceivID,
  A.XmitID,
  MAX(IIF(B.XTStamp<= A.RecTStamp,B.XTStamp,Null)) as BeforeXTStamp,
  MIN(IIF(B.XTStamp > A.RecTStamp,B.XTStamp,Null)) as AfterXTStamp
FROM FirstTable as A
INNER JOIN SecondTable as B ON 
  (A.RecTStamp<>B.XTStamp OR A.RecTStamp=B.XTStamp)
GROUP BY A.RecTStamp, A.ReceivID, A.XmitID
  -- alternative for BeforeXTStamp MAX(-(B.XTStamp<=A.RecTStamp)*B.XTStamp)
  -- alternatives for AfterXTStamp (see "Aside" note below)
  -- 1.0/(MAX(1.0/(-(B.XTStamp>A.RecTStamp)*B.XTStamp)))
  -- -1.0/(MIN(1.0/((B.XTStamp>A.RecTStamp)*B.XTStamp)))

দ্বিতীয় (ধীর)

SELECT
  A.RecTStamp, AbyB1.XTStamp AS BeforeXTStamp, AbyB2.XTStamp AS AfterXTStamp
FROM (FirstTable AS A INNER JOIN 
  (select top 1 B1.XTStamp, A1.RecTStamp 
   from SecondTable as B1, FirstTable as A1
   where B1.XTStamp<=A1.RecTStamp
   order by B1.XTStamp DESC) AS AbyB1 --MAX (time points before)
ON A.RecTStamp = AbyB1.RecTStamp) INNER JOIN 
  (select top 1 B2.XTStamp, A2.RecTStamp 
   from SecondTable as B2, FirstTable as A2
   where B2.XTStamp>A2.RecTStamp
   order by B2.XTStamp ASC) AS AbyB2 --MIN (time points after)
ON A.RecTStamp = AbyB2.RecTStamp; 

পটভূমি

আমার কাছে একটি DateTimeস্ট্যাম্প, ট্রান্সমিটার আইডি এবং রেকর্ডিং ডিভাইস আইডির উপর ভিত্তি করে একটি যৌগিক প্রাথমিক কী সহ 1 মিলিয়ন এর নিচে একটি টেলিমেট্রি টেবিল (এ হিসাবে এলিয়াসযুক্ত) রয়েছে । আমার নিয়ন্ত্রণের বাইরে অবস্থার কারণে, আমার এসকিউএল ভাষা হ'ল মাইক্রোসফ্ট অ্যাক্সেসের স্ট্যান্ডার্ড জেট ডিবি (ব্যবহারকারীরা 2007 এবং পরবর্তী সংস্করণগুলি ব্যবহার করবেন)। এই এন্ট্রিগুলির মধ্যে প্রায় 200,000 ট্রান্সমিটার আইডির কারণে ক্যোয়ারীর সাথে প্রাসঙ্গিক।

একটি দ্বিতীয় টেলিমেট্রি টেবিল রয়েছে (ওরফে বি) যার মধ্যে একটি একক সহ প্রায় 50,000 এন্ট্রি জড়িত DateTime প্রাথমিক কী

প্রথম পদক্ষেপের জন্য, আমি দ্বিতীয় টেবিল থেকে প্রথম টেবিলের স্ট্যাম্পগুলির নিকটতম টাইমস্ট্যাম্পগুলি সন্ধান করার দিকে মনোনিবেশ করেছি।


যোগদান ফলাফল

যে আবিষ্কারগুলি আমি আবিষ্কার করেছি ...

... ডিবাগিংয়ের সময় পথে

এটি JOINযুক্তিটি লিখলে সত্যই অদ্ভুত লাগে FROM FirstTable as A INNER JOIN SecondTable as B ON (A.RecTStamp<>B.XTStamp OR A.RecTStamp=B.XTStamp)যেহেতু @ বার্ডজেয়ে একটি মন্তব্যে উল্লেখ করেছেন (যেহেতু অদৃশ্য হয়ে গেছে) ক্রস- জয়েনের একটি রূপ। লক্ষ্য করুন বদলে LEFT OUTER JOINজন্য INNER JOINপ্রদর্শিত হয় উপরে কোডে পরিমাণ বা লাইন ফিরে পরিচয় কোন প্রভাব তৈরি করতে হবে। আমিও অন ক্লজটি ছেড়ে দিতে বা বলতে পারি না ON (1=1)। (A <> B বা A = B) স্পষ্টরূপে প্রত্যাবর্তন হিসাবে সারণিতে A সারণীতে কেবলমাত্র একটি লাইন পরিবর্তে সারিগুলির পরিবর্তে ( INNERবা এর চেয়ে LEFT OUTER JOIN) পরিবর্তনের জন্য কমা ব্যবহার করে Count(select * from A) * Count(select * from B)এই ক্যোয়ারিতে JOINফিরে এসেছে। এটি স্পষ্টভাবে উপযুক্ত নয়। FIRSTকোনও যৌগিক প্রাথমিক কী ধরণের দেওয়া ব্যবহারের জন্য উপলব্ধ বলে মনে হচ্ছে না।

দ্বিতীয় JOINশৈলী, যদিও যুক্তিযুক্তভাবে আরও সুস্পষ্ট, তত ধীরে ধীরে ভুগছে। এটি হতে পারে কারণ JOINবৃহত টেবিলের বিপরীতে CROSS JOINউভয় বিকল্পে পাওয়া দুটি অতিরিক্ত অভ্যন্তর প্রয়োজন ।

অন্যদিকে: IIFধারাটির সাথে প্রতিস্থাপন MIN/ MAXএকই সংখ্যক এন্ট্রি ফিরিয়ে দেয়।
MAX(-(B.XTStamp<=A.RecTStamp)*B.XTStamp)
"পূর্বে" ( MAX) টাইমস্ট্যাম্পের জন্য কাজ করে, তবে নিম্নলিখিত "পরে" ( MIN) এর জন্য সরাসরি কাজ করে না :
MIN(-(B.XTStamp>A.RecTStamp)*B.XTStamp)
কারণ সর্বনিম্ন সর্বদা FALSEশর্তের জন্য 0 হয় । এই 0 কোনও পূর্ব -যুগের চেয়ে কম DOUBLE(কোন DateTimeক্ষেত্রটি অ্যাক্সেসের একটি উপসেট এবং এই গণনাটি ক্ষেত্রটিকে রূপান্তর করে)। IIFএবং MIN/ MAXপদ্ধতি বিকল্পসমূহ শূন্য দ্বারা কারণ বিভাজন AfterXTStamp মান কাজের জন্য প্রস্তাবিত ( FALSE) নাল মান, যা সমষ্টিগত ফাংশন MIN এবং MAX উপর লাফালাফি জেনারেট করে।

পরবর্তী পদক্ষেপ

এটিকে আরও এগিয়ে নিয়ে যাওয়ার জন্য, আমি দ্বিতীয় টেবিলের টাইমস্ট্যাম্পগুলি সন্ধান করতে চাই যা সরাসরি প্রথম টেবিলের টাইমস্ট্যাম্পগুলি সরাসরি ফ্ল্যাঙ্ক করে এবং those পয়েন্টগুলির সময় দূরত্বের উপর ভিত্তি করে দ্বিতীয় সারণী থেকে ডেটা মানগুলির একটি রৈখিক প্রবৃদ্ধি সম্পাদন করে (যেমন যদি টাইমস্ট্যাম্প থেকে প্রথম টেবিলটি "আগে" এবং "পরে" এর মধ্যে 25% পথ হিসাবে গণনা করা মানের 25% "" পরে "পয়েন্টের সাথে এবং" আগে "থেকে 75% এর সাথে যুক্ত দ্বিতীয় সারণির মান ডেটা থেকে আসা উচিত )। অভ্যন্তরীণ সাহসের অংশ হিসাবে সংশোধিত যোগদানের ধরণটি ব্যবহার করে, এবং নীচের প্রস্তাবিত উত্তরগুলির পরে আমি উত্পন্ন করি ...

    SELECT
        AvgGPS.XmitID,
        StrDateIso8601Msec(AvgGPS.RecTStamp) AS RecTStamp_ms,
        -- StrDateIso8601MSec is a VBA function returning a TEXT string in yyyy-mm-dd hh:nn:ss.lll format
        AvgGPS.ReceivID,
        RD.Receiver_Location_Description,
        RD.Lat AS Receiver_Lat,
        RD.Lon AS Receiver_Lon,
        AvgGPS.Before_Lat * (1 - AvgGPS.AfterWeight) + AvgGPS.After_Lat * AvgGPS.AfterWeight AS Xmit_Lat,
        AvgGPS.Before_Lon * (1 - AvgGPS.AfterWeight) + AvgGPS.After_Lon * AvgGPS.AfterWeight AS Xmit_Lon,
        AvgGPS.RecTStamp AS RecTStamp_basic
    FROM ( SELECT 
        AfterTimestampID.RecTStamp,
        AfterTimestampID.XmitID,
        AfterTimestampID.ReceivID,
        GPSBefore.BeforeXTStamp, 
        GPSBefore.Latitude AS Before_Lat, 
        GPSBefore.Longitude AS Before_Lon,
        GPSAfter.AfterXTStamp, 
        GPSAfter.Latitude AS After_Lat, 
        GPSAfter.Longitude AS After_Lon,
        ( (AfterTimestampID.RecTStamp - GPSBefore.XTStamp) / (GPSAfter.XTStamp - GPSBefore.XTStamp) ) AS AfterWeight
        FROM (
            (SELECT 
                ReceiverRecord.RecTStamp, 
                ReceiverRecord.ReceivID, 
                ReceiverRecord.XmitID,
               (SELECT TOP 1 XmitGPS.X_ID FROM SecondTable as XmitGPS WHERE ReceiverRecord.RecTStamp < XmitGPS.XTStamp ORDER BY XmitGPS.X_ID) AS AfterXmit_ID
             FROM FirstTable AS ReceiverRecord 
             -- WHERE ReceiverRecord.XmitID IN (select XmitID from ValidXmitters)
             GROUP BY RecTStamp, ReceivID, XmitID
            ) AS AfterTimestampID INNER JOIN SecondTable AS GPSAfter ON AfterTimestampID.AfterXmit_ID = GPSAfter.X_ID
        ) INNER JOIN SecondTable AS GPSBefore ON AfterTimestampID.AfterXmit_ID = GPSBefore.X_ID + 1
    ) AS AvgGPS INNER JOIN ReceiverDetails AS RD ON (AvgGPS.ReceivID = RD.ReceivID) AND (AvgGPS.RecTStamp BETWEEN RD.Beginning AND RD.Ending)
    ORDER BY AvgGPS.RecTStamp, AvgGPS.ReceivID;

... যা প্রত্যাশিত রেকর্ডের চূড়ান্ত সংখ্যায় (কমপক্ষে আনুমানিক) অনুসারে 152928 রেকর্ড দেয়। রান টাইম সম্ভবত আমার আই 7-4790, 16 জিবি র‌্যাম, এসএসডি নেই, উইন 8.1 প্রো সিস্টেমের 5-10 মিনিট।


রেফারেন্স 1: এমএস অ্যাক্সেস মিলিসেকেন্ড সময় মানগুলি পরিচালনা করতে পারে - সত্যই এবং তার সাথে উত্স ফাইল [08080011.txt]

উত্তর:


10

অ্যাক্সেস ডিবি দিয়ে এমন কিছু করার জন্য আপনার সাহসের জন্য প্রথমে আপনাকে অবশ্যই প্রশংসা করতে হবে, যা আমার অভিজ্ঞতা থেকে এসকিউএল-জাতীয় কিছু করা খুব কঠিন । যাইহোক, পর্যালোচনা করার জন্য।


প্রথমে যোগ দিন

আপনার IIFক্ষেত্র নির্বাচনগুলি পরিবর্তে একটি স্যুইচ বিবৃতি ব্যবহার করে উপকৃত হতে পারে । কখনও কখনও এটি ক্ষেত্রে বিশেষত এসকিউএল জিনিসগুলির সাথে মনে হয় যে একটি SWITCH(সাধারণত CASEসাধারণত এসকিউএল হিসাবে পরিচিত ) খুব দ্রুত হয় যখন এ এর ​​শরীরে সহজ তুলনা করা হয় SELECT। আপনার ক্ষেত্রে সিনট্যাক্সটি প্রায় অভিন্ন হবে, যদিও একটি ক্ষেত্রের তুলনায় একটি বড় অংশকে coverাকতে একটি স্যুইচ প্রসারিত করা যেতে পারে। কিছু বিবেচনা করার।

  SWITCH (
    expr1, val1,
    expr2, val2,
    val3        -- default value or "else"
  )

একটি স্যুইচ বৃহত্তর বিবৃতিতে পাঠযোগ্যতাও সহায়তা করতে পারে। প্রেক্ষাপটে:

  MAX(SWITCH(B.XTStamp <= A.RecTStamp,B.XTStamp,Null)) as BeforeXTStamp,
  --alternatively MAX(-(B.XTStamp<=A.RecTStamp)*B.XTStamp) as BeforeXTStamp,
  MIN(SWITCH(B.XTStamp>A.RecTStamp,B.XTStamp,Null)) as AfterXTStamp

যোগদানের জন্য নিজেই, আমি মনে করি (A.RecTStamp<>B.XTStamp OR A.RecTStamp=B.XTStamp)আপনি যা করার চেষ্টা করছেন তা দেওয়া হিসাবে আপনি যতটা লাভ করছেন। এটি এত দ্রুত নয়, তবে আমি এটিও হয় না বলে আশা করব না।


দ্বিতীয় যোগদান

আপনি বলেছিলেন এটি ধীর। এটি কোনও কোডের দৃষ্টিকোণ থেকে কম পাঠযোগ্য able 1 এবং 2 এর মধ্যে সমানভাবে সন্তোষজনক ফলাফলের সেট দেওয়া, আমি বলব 1 এর জন্য যান At আপনি যেভাবে চেষ্টা করছেন তা কমপক্ষে এটি স্পষ্ট। সাবকিউরিগুলি প্রায়শই খুব দ্রুত হয় না (যদিও প্রায়শই অনিবার্য নয়) বিশেষত এক্ষেত্রে আপনি প্রত্যেকটিতে একটি অতিরিক্ত যোগদানের জন্য নিক্ষেপ করছেন যা অবশ্যই মৃত্যুদণ্ড কার্যকর করার পরিকল্পনাটিকে জটিল করে তুলবে।

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

FROM (FirstTable AS A INNER JOIN 
  (select top 1 B1.XTStamp, A1.RecTStamp 
   from SecondTable as B1
   inner join FirstTable as A1
     on B1.XTStamp <= A1.RecTStamp
   order by B1.XTStamp DESC) AS AbyB1 --MAX (time points before)

নামকরণ জিনিস

আমি মনে করি যেভাবে আপনার জিনিসগুলির নামকরণ করা হয়েছে তা সর্বদাই অসহনীয় এবং সবচেয়ে রহস্যজনক। A, B, A1, B1টেবিল এলিয়াস হিসাবে আমি মনে করি আরও ভাল হতে পারে। এছাড়াও, আমি ফিল্ডের নামগুলি খুব ভাল না বলে মনে করি, তবে আমি বুঝতে পারি এটির উপর আপনার নিয়ন্ত্রণ নাও থাকতে পারে। জিনিসগুলির নামকরণের বিষয়টিতে আমি কেবল কোডলেস কোডটি খুব শীঘ্রই উদ্ধৃত করব এবং এটিকে রেখে দেব ...

পুরোহিতদের উত্তর দিলেন "উদ্দীপনা!" "আপনার এক্সপ্লিটিভ বিশেষ্য ক্রিয়া!"


"পরবর্তী পদক্ষেপ" ক্যোয়ারী

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

  • 2 স্পেসের পরিবর্তে 4 স্পেস ইনডেন্ট করুন
  • গাণিতিক এবং তুলনা অপারেটরগুলির চারপাশের স্পেস
  • ব্রেস এবং ইন্ডেন্টেশন আরও প্রাকৃতিক স্থাপনা (আমি জাভা-শৈলীর ধনুর্বন্ধনী সঙ্গে গিয়েছিলাম, কিন্তু আপনার পছন্দ অনুযায়ী সি স্টাইল হতে পারে)

দেখা যাচ্ছে যেহেতু এটি সত্যিই একটি জটিল প্রশ্ন। এটি অনুধাবন করার জন্য, আমাকে অন্তিমতম কোয়েরি থেকে শুরু করতে হবে, আপনার IDডেটা সেট, যা আমি বুঝতে পেরেছি তা আপনার প্রথম যোগদানের সমান। এটি আপনার আগ্রহী ডিভাইসের সাবসেটের মধ্যে টাইমস্ট্যাম্পগুলির আগে / পরে সবচেয়ে কাছের অবস্থিত ডিভাইসের আইডি এবং টাইমস্ট্যাম্পগুলি ফিরিয়ে দেয় So সুতরাং পরিবর্তে IDকেন এটি কল করবেন না ClosestTimestampID

আপনার Detযোগদানটি একবার ব্যবহার করা হবে:

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

বাকি সময়টি কেবলমাত্র আপনার ইতিমধ্যে প্রাপ্ত মানগুলিতে যোগ দেয় ClosestTimestampID। সুতরাং পরিবর্তে আমাদের কেবল এটি করতে সক্ষম হওয়া উচিত:

    ) AS ClosestTimestampID
    INNER JOIN SecondTable AS TL1 
        ON ClosestTimestampID.BeforeXTStamp = TL1.XTStamp) 
    INNER JOIN SecondTable AS TL2 
        ON ClosestTimestampID.AfterXTStamp = TL2.XTStamp
    WHERE ClosestTimestampID.XmitID IN (<limited subset S>)

সম্ভবত একটি বিশাল পারফরম্যান্স লাভ নাও হতে পারে, তবে দরিদ্র জেট ডিবি অপ্টিমাইজারকে সহায়তা করতে আমরা যা কিছু করতে পারি তা সহায়তা করবে!


আমি এই অনুভূতিটি কাঁপতে পারি না যে আপনি যে গণনাগুলি / অ্যালগরিদম ব্যবহার করেছেন BeforeWeightএবং AfterWeightযেগুলি আপনি ইন্টারপোল্ট করতে ব্যবহার করেন তা আরও ভালভাবে করা যেতে পারে, তবে দুর্ভাগ্যক্রমে আমি সেগুলির সাথে খুব ভাল নই।

ক্র্যাশ হওয়া এড়াতে একটি পরামর্শ (যদিও এটি আপনার প্রয়োগের উপর নির্ভর করে আদর্শ নয়) আপনার নেস্টেড সাবকুইরিগুলি তাদের নিজস্ব টেবিলগুলিতে ছড়িয়ে দেওয়া এবং যখন প্রয়োজন হবে তখন আপডেট করা। আমি নিশ্চিত না যে আপনার উত্সের তথ্যটি কতবার রিফ্রেশ করার জন্য আপনাকে প্রয়োজন হয় তবে আপনি যদি প্রায়শই এটি না করেন তবে আপনি টেবিলগুলি এবং উত্পন্ন টেবিলগুলির আপডেটের জন্য কিছু ভিবিএ কোড লেখার কথা ভাবতে পারেন এবং টানতে কেবল আপনার বহিরাগত কোয়েরিটি ছেড়ে যান মূল উত্সের পরিবর্তে সেই টেবিলগুলি থেকে। কেবল একটি চিন্তাধারা, যেমন আমি বলেছিলাম আদর্শ নয় তবে সরঞ্জামটি দেওয়া হয়েছে আপনার পছন্দ নাও থাকতে পারে।


সবকিছু একসাথে:

SELECT
    InGPS.XmitID,
    StrDateIso8601Msec(InGPS.RecTStamp) AS RecTStamp_ms,
       -- StrDateIso8601MSec is a VBA function returning a TEXT string in yyyy-mm-dd hh:nn:ss.lll format
    InGPS.ReceivID,
    RD.Receiver_Location_Description,
    RD.Lat AS Receiver_Lat,
    RD.Lon AS Receiver_Lon,
    InGPS.Before_Lat * InGPS.BeforeWeight + InGPS.After_Lat * InGPS.AfterWeight AS Xmit_Lat,
    InGPS.Before_Lon * InGPS.BeforeWeight + InGPS.After_Lon * InGPS.AfterWeight AS Xmit_Lon,
    InGPS.RecTStamp AS RecTStamp_basic
FROM (
    SELECT 
        ClosestTimestampID.RecTStamp,
        ClosestTimestampID.XmitID,
        ClosestTimestampID.ReceivID,
        ClosestTimestampID.BeforeXTStamp, 
        TL1.Latitude AS Before_Lat, 
        TL1.Longitude AS Before_Lon,
        (1 - ((ClosestTimestampID.RecTStamp - ClosestTimestampID.BeforeXTStamp) 
            / (ClosestTimestampID.AfterXTStamp - ClosestTimestampID.BeforeXTStamp))) AS BeforeWeight,
        ClosestTimestampID.AfterXTStamp, 
        TL2.Latitude AS After_Lat, 
        TL2.Longitude AS After_Lon,
        (     (ClosestTimestampID.RecTStamp - ClosestTimestampID.BeforeXTStamp) 
            / (ClosestTimestampID.AfterXTStamp - ClosestTimestampID.BeforeXTStamp)) AS AfterWeight
        FROM (((
            SELECT 
                A.RecTStamp, 
                A.ReceivID, 
                A.XmitID,
                MAX(SWITCH(B.XTStamp <= A.RecTStamp, B.XTStamp, Null)) AS BeforeXTStamp,
                MIN(SWITCH(B.XTStamp > A.RecTStamp, B.XTStamp, Null)) AS AfterXTStamp
            FROM FirstTable AS A
            INNER JOIN SecondTable AS B 
                ON (A.RecTStamp <> B.XTStamp OR A.RecTStamp = B.XTStamp)
            WHERE A.XmitID IN (<limited subset S>)
            GROUP BY A.RecTStamp, ReceivID, XmitID
        ) AS ClosestTimestampID
        INNER JOIN FirstTable AS Det 
            ON (Det.XmitID = ClosestTimestampID.XmitID) 
            AND (Det.ReceivID = ClosestTimestampID.ReceivID) 
            AND (Det.RecTStamp = ClosestTimestampID.RecTStamp)) 
        INNER JOIN SecondTable AS TL1 
            ON ClosestTimestampID.BeforeXTStamp = TL1.XTStamp) 
        INNER JOIN SecondTable AS TL2 
            ON ClosestTimestampID.AfterXTStamp = TL2.XTStamp
        WHERE Det.XmitID IN (<limited subset S>)
    ) AS InGPS
INNER JOIN ReceiverDetails AS RD 
    ON (InGPS.ReceivID = RD.ReceivID) 
    AND (InGPS.RecTStamp BETWEEN <valid parameters from another table>)
ORDER BY StrDateIso8601Msec(InGPS.RecTStamp), InGPS.ReceivID;

5
  • অতিরিক্ত বৈশিষ্ট্য এবং ফিল্টার শর্ত যুক্ত করা হয়েছে।
  • ন্যূনতম এবং সর্বাধিক নেস্টেড ক্যোয়ারী ব্যবহার করে ক্রস জয়েনের যে কোনও ফর্মকে মুছে ফেলা হয়। এটিই সবচেয়ে বড় পারফরম্যান্স লাভ।
  • অভ্যন্তরীণ সর্বাধিক নেস্টেড ক্যোয়ারী দ্বারা প্রাপ্ত ন্যূনতম এবং সর্বাধিক ফ্ল্যাঙ্ক মানগুলি হ'ল প্রাথমিক কী মান (স্ক্যান) যা চূড়ান্ত গণনার জন্য সন্ধান করে অতিরিক্ত ফ্ল্যাঙ্ক বৈশিষ্ট্য (ল্যাট এবং লোন) পুনরুদ্ধার করতে ব্যবহৃত হয় (অ্যাক্সেসের প্রয়োগের সমতুল্য থাকে)।
  • প্রাথমিক টেবিলের বৈশিষ্ট্যগুলি অভ্যন্তরীণতম কোয়েরিতে পুনরুদ্ধার করা এবং ফিল্টার করা হয় এবং তার সম্পাদনায় সহায়তা করা উচিত।
  • বাছাইয়ের সময় মান (StrDateIso8601Msec) বিন্যাস করার দরকার নেই। টেবিল থেকে ডেটটাইম মান ব্যবহার করা সমতুল্য।

SQL সার্ভার এক্সেকিউশন প্ল্যান (কারণ অ্যাক্সেস প্রদর্শন করতে পারবে না)
দ্বারা কারণ এটির ব্যয়বহুল চূড়ান্ত আদেশ ছাড়া:
। ক্লাস্টার ইনডেক্স স্ক্যান [ReceiverDetails] [PK_ReceiverDetails] খরচ 16%
ক্লাস্টার ইনডেক্স খোঁজ [FirstTable] [PK_FirstTable] খরচ 19%।
ক্লাস্টার ইনডেক্স [সেকেন্ড টেবিল] সন্ধান করুন [[পিকে_সেকেন্ড টেবিল] 16%
ক্লাস্টারড ইনডেক্স অনুসন্ধান করুন [সেকেন্ড টেবিল] [[পিকে_সেকেন্ড টেবিল] ব্যয় 16%
ক্লাস্টারড ইনডেক্স সিক [সেকেন্ড টেবিল] [[পিকে_সেকেন্ড টেবিল] [টিএল 2] 16%
ক্লাস্টারড ইনডেক্স সিক [সেকেন্ড টেবিল]। [পি কে_সেকেন্ডটেবল] [টিএল 1]

চূড়ান্ত অর্ডার দিয়ে 16% ব্যয় করে:
বাছাই করুন 36%
ক্লাস্টারড ইনডেক্স স্ক্যান
ক্লাস্টারড ইনডেক্স সন্ধান করুন [ফার্স্ট টেবিল] [
ক্লাস্টারড ইনডেক্স সেকেন্ড [সেকেন্ড টেবিল]। [পিকে_সেকেন্ড টেবিল] 10%
ক্লাস্টারড ইনডেক্স সেকেন্ড [সেকেন্ড টেবিল]। [পিকে_সেকেন্ড টেবিল] ব্যয় 10%
ক্লাস্টারড ইনডেক্স সিক [সেকেন্ড টেবিল]। [পিকেএস সেকেন্ড টেবিল] [টিএল 2] 10%
ক্লাস্টারড ইনডেক্স সিক [সেকেন্ড টেবিল] [। পিকে_সেকেন্ড টেবিল] [টিএল 1] মূল্য 10%

কোড:

select
     ClosestTimestampID.XmitID
    --,StrDateIso8601Msec(InGPS.RecTStamp) AS RecTStamp_ms
    ,ClosestTimestampID.ReceivID
    ,ClosestTimestampID.Receiver_Location_Description
    ,ClosestTimestampID.Lat
    ,ClosestTimestampID.Lon
,[TL1].[Latitude] * (1 - ((ClosestTimestampID.RecTStamp - ClosestTimestampID.BeforeXTStamp) / (ClosestTimestampID.AfterXTStamp - ClosestTimestampID.BeforeXTStamp))) + [TL2].[Latitude] * ((ClosestTimestampID.RecTStamp - ClosestTimestampID.BeforeXTStamp) / (ClosestTimestampID.AfterXTStamp - ClosestTimestampID.BeforeXTStamp)) AS Xmit_Lat
,[TL1].[Longitude] * (1 - ((ClosestTimestampID.RecTStamp - ClosestTimestampID.BeforeXTStamp) / (ClosestTimestampID.AfterXTStamp - ClosestTimestampID.BeforeXTStamp))) + [TL2].[Longitude] * ((ClosestTimestampID.RecTStamp - ClosestTimestampID.BeforeXTStamp) / (ClosestTimestampID.AfterXTStamp - ClosestTimestampID.BeforeXTStamp)) AS Xmit_Lon
    ,ClosestTimestampID.RecTStamp as RecTStamp_basic
from (
        (
            (
                select
                     FirstTable.RecTStamp
                    ,FirstTable.ReceivID
                    ,FirstTable.XmitID
                    ,ReceiverDetails.Receiver_Location_Description
                    ,ReceiverDetails.Lat
                    ,ReceiverDetails.Lon
                    ,(
                        select max(XTStamp) as val
                        from SecondTable
                        where XTStamp <= FirstTable.RecTStamp
                     ) as BeforeXTStamp
                    ,(
                        select min(XTStamp) as val
                        from SecondTable
                        where XTStamp > FirstTable.RecTStamp
                     ) as AfterXTStamp
                from FirstTable
                inner join ReceiverDetails
                on ReceiverDetails.ReceivID = FirstTable.ReceivID
                where FirstTable.RecTStamp between #1/1/1990# and #1/1/2020#
                and FirstTable.XmitID in (100,110)
            ) as ClosestTimestampID
            inner join SecondTable as TL1
            on ClosestTimestampID.BeforeXTStamp = TL1.XTStamp
        )
        inner join SecondTable as TL2
        on ClosestTimestampID.AfterXTStamp = TL2.XTStamp
    )
order by ClosestTimestampID.RecTStamp, ClosestTimestampID.ReceivID;

ক্রোস জয়েন থাকা ক্যোয়ারীর বিপরীতে আমার ক্যোয়ারী পরীক্ষার পারফরম্যান্স।

ফার্স্ট টেবিলটি 13 টি রেকর্ড এবং দ্বিতীয় সারণী 1,000,000 দিয়ে লোড করা হয়েছিল।
আমার প্রশ্নের জন্য মৃত্যুদন্ড কার্যকর করার পরিকল্পনাগুলি যা পোস্ট করা হয়েছে তার থেকে খুব বেশি পরিবর্তন হয়নি।
ক্রুশের জন্য এক্সিকিউশন পরিকল্পনা যোগ দিন:
নেস্টেড loops খরচ ব্যবহার 81% INNER JOIN SecondTable AS B ON (A.RecTStamp <> B.XTStamp OR A.RecTStamp = B.XTStamp
যদি নেস্টেড loops 75% ড্রপ ব্যবহার CROSS JOIN SecondTable AS B' or ',SecondTable AS B
স্ট্রিম মোট 8%
ইনডেক্স স্ক্যান [SecondTable] [UK_ID] [বি] 6%
ছক নাটাই 5%
বেশ অন্যান্য ক্লাস্টার ইনডেক্স খোঁজ এবং ইনডেক্স আহ্বান (পোস্ট হিসাবে আমার প্রশ্নের অনুরূপ) 0% খরচ সহ।

আমার ক্যোয়ারি এবং ক্রস জয়েনের জন্য নির্বাহের সময় .007 এবং 8-9 সেকেন্ড।
ব্যয় তুলনা 0% এবং 100%।

আমি যোগদানের শর্তের জন্য রিসিভারডেটেলগুলিতে 50,000 রেকর্ড এবং একটি একক রেকর্ড সহ ফার্স্ট টেবিল লোড করেছি এবং আমার জিজ্ঞাসা চালিয়েছি।
50,013 0.9 এবং 1.0 সেকেন্ডের মধ্যে ফিরে এসেছিল।

আমি ক্রস যোগ দিয়ে দ্বিতীয় ক্যোয়ারী চালিয়েছিলাম এবং এটি মারার আগে প্রায় 20 মিনিটের জন্য এটি চালানোর অনুমতি দেয়।
যদি ক্রস জয়েন কোয়েরিটি কেবলমাত্র মূল 13 টি ফেরত দিতে ফিল্টার করা হয় তবে এক্সিকিউশন সময়টি আবার 8-9 সেকেন্ড হয়।
ফিল্টার শর্তের অবস্থানটি সবচেয়ে বেশি নির্বাচিত, বহিরাগত সর্বাধিক নির্বাচিত এবং উভয়ই ছিল at কোনও পার্থক্য নেই।

ক্রস জোনের পক্ষে এই দুটি যোগ শর্তের মধ্যে পার্থক্য রয়েছে, প্রথমটি একটি শিকারী ব্যবহার করে, ক্রস যোগ দেয় না:
INNER JOIN SecondTable AS B ON (A.RecTStamp <> B.XTStamp OR A.RecTStamp = B.XTStamp) CROSS JOIN SecondTable AS B


আমার সিস্টেমে ক্লোজস্টটাইমস্ট্যাম্পিড অংশটি চালানোর সাথে সাথে একটি গণনা (*) এ এনপ্যাপুলেটেড হওয়ার সাথে সাথে 152928 রেকর্ডগুলি ফিরে আসে। সেই পর্যায়ে প্রকৃত রেকর্ডগুলি ফিরিয়ে দেওয়ার সময় আমার এমএসএ্যাকস লকআপ হয়ে গেছে - অন্য পদ্ধতি থেকে টেম্প টেবিলগুলি সমস্ত ধরণের স্মৃতিতে জড়িয়ে ছিল। আমি মনে করি আপনার পদ্ধতি থেকে আমি যে চূড়ান্ত ক্যোয়ারী উত্পন্ন করি তা বর্তমানে আমি যেভাবে ব্যবহার করছি তার সাথে খুব মিল হবে। যা আমি মনে করি এটি একটি ভাল জিনিস :)
mpag

1
আপনার মূল মন্তব্যে আপনি ইঙ্গিত করেছেন যে আপনি কিছু রেকর্ড অবিলম্বে ফিরে পেয়েছেন। অ্যাক্সেস কীভাবে কাজ করে, অ্যাক্সেস কৌশল নিয়ে আসে এবং সম্পাদনের সময়টির জন্য প্রত্যাশাগুলি নির্ধারণ করে সে ক্ষেত্রে এটি গুরুত্বপূর্ণ। একে বলা হয় মুলতুবি কার্যকর করা। (আপনি সর্বশেষ রেকর্ডটি আঘাত করার সময় এটি ক্র্যাশ হয়েছিল)) চূড়ান্ত ক্যোয়ারীতে উচ্চ সীমা রিটার্নের রেকর্ড গণনাটি কতটা প্রত্যাশিত?
byrdzeye

আমি বিশ্বাস করি 152928
এমপিগ

নতুন রেকর্ড যুক্ত হওয়ার সাথে সাথে উভয় টেবিলে ডেটটাইম মানগুলির প্রকৃতি কী। সেগুলি কি বর্তমান সময়ের স্ট্যাম্প বা সাম্প্রতিক মান বা সম্পূর্ণ র্যান্ডম?
byrdzeye

প্রথম টেবিলটিতে ডেটটাইম স্ট্যাম্প রয়েছে যা 2013 বা আরও সাম্প্রতিক। দ্বিতীয় সারণীতে ডেটটাইম স্ট্যাম্পগুলি রয়েছে যা ২০১৫ সালের মাঝামাঝি কয়েক মাসের মধ্যে রয়েছে new নতুন মান যুক্ত করা হলে সেগুলি বিদ্যমান সেট পরে সম্ভবত (তবে নিশ্চিত হতে পারে না)। যে কোনও টেবিলে নতুন মান যুক্ত করা যেতে পারে।
এমপ্যাগ

2

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

--*** Create a table for flank values.
    create table Flank (
         RecTStamp      datetime not null
        ,BeforeXTStamp  datetime null
        ,AfterXTStamp   datetime null
        ,constraint PK_Flank primary key clustered ( RecTStamp asc )
        )

--*** Create a FlankUpdateLoop sub. (create what is missing)
    -- loop until rowcount < 5000 or rowcount = 0
    -- a 5K limit appears to be manageable for Access, especially for the initial population.
    insert into Flank (
         RecTStamp
        ,BeforeXTStamp
        ,AfterXTStamp
        )
    select top 5000 FirstTable.RecTStamp
        ,(
            select max(XTStamp) as val
            from SecondTable
            where XTStamp <= FirstTable.RecTStamp
            ) as BeforeXTStamp
        ,(
            select min(XTStamp) as val
            from SecondTable
            where XTStamp > FirstTable.RecTStamp
            ) as AfterXTStamp
    from FirstTable
    left join Flank
        on FirstTable.RecTStamp = Flank.RecTStamp
    where Flank.RecTStamp is null;

--*** For FirstTable Adds, Changes or Deletes:
    delete from Flank where Flank.RecTStamp = CRUD_RecTStamp
    execute FlankUpdateLoop --See above. This will handle Adds, Changes or Deletes.

--*** For SecondTable Adds, Changes or Deletes:
    --delete from Flank where the old value is immediately before and after the new flank value.
    --They may or may not get be assigned a new value. Let FlankUpdate figure it out.

    --execute deletes for both beforextstamp and afterxtstamp
    --then update flank

    delete *
    from flank
    where beforextstamp between (
                    select min(beforextstamp)
                    from flank
                    where beforextstamp >= '3/16/2009 10:00:46 AM'
                    ) and (
                    select max(beforextstamp)
                    from flank
                    where beforextstamp <= '3/16/2009 10:00:46 AM'
                    );

    delete *
    from flank
    where afterxtstamp between (
                    select min(afterxtstamp)
                    from flank
                    where afterxtstamp >= '3/16/2009 10:00:46 AM'
                    ) and (
                    select max(afterxtstamp)
                    from flank
                    where afterxtstamp <= '3/16/2009 10:00:46 AM'
                    );

    execute FlankUpdateLoop

--*** Final Report Query***--
    --Should execute without issues including 'deferred execution' problem.
    --Add filters as needed.
    select FirstTable.XmitID
        ,FirstTable.ReceivID
        ,ReceiverDetails.Lat
        ,ReceiverDetails.Lon
        ,BeforeTable.Latitude * (1 - ((FirstTable.RecTStamp - BeforeXTStamp) / (AfterXTStamp - BeforeXTStamp))) + AfterTable.Latitude * ((FirstTable.RecTStamp - BeforeXTStamp) / (AfterXTStamp - BeforeXTStamp)) as Xmit_Lat
        ,BeforeTable.Longitude * (1 - ((FirstTable.RecTStamp - BeforeXTStamp) / (AfterXTStamp - BeforeXTStamp))) + AfterTable.Longitude * ((FirstTable.RecTStamp - BeforeXTStamp) / (AfterXTStamp - BeforeXTStamp)) as Xmit_Lon
        ,FirstTable.RecTStamp as RecTStamp_basic
    from (((
        FirstTable
    inner join Flank on FirstTable.RecTStamp = Flank.RecTStamp)
    inner join SecondTable as BeforeTable on Flank.BeforeXTStamp = BeforeTable.XTStamp)
    inner join SecondTable as AfterTable on Flank.AfterXTStamp = AfterTable.XTStamp)
    inner join ReceiverDetails on FirstTable.ReceivID = ReceiverDetails.ReceivID
    order by FirstTable.RecTStamp;
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.