প্রতিটি পরপর সিরিজের সারির মোট সময়কাল সন্ধান করুন


11

মাইএসকিউএল সংস্করণ

কোডটি মাইএসকিউএল 5.5 এ চলবে

পটভূমি

আমার নীচের মত একটি টেবিল আছে

CREATE TABLE t
( id INT NOT NULL AUTO_INCREMENT
, patient_id INT NOT NULL
, bed_id INT NOT NULL
, ward_id INT NOT NULL
, admitted DATETIME NOT NULL
, discharged DATETIME
, PRIMARY KEY (id)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;

এই টেবিলটি হাসপাতালের রোগীদের সম্পর্কে এবং এটি বিছানাগুলি সংরক্ষণ করে যেখানে প্রতিটি রোগী হাসপাতালে ভর্তি হওয়ার সময় কিছুটা সময় ব্যয় করেছিলেন।

প্রতিটি ওয়ার্ডে একাধিক শয্যা থাকতে পারে এবং প্রতিটি রোগী একই ওয়ার্ডের মধ্যে একটি পৃথক বিছানায় যেতে পারেন।

উদ্দেশ্য

আমি যা করতে চাই তা হ'ল প্রতিটি রোগী একটি আলাদা ওয়ার্ডে না গিয়ে নির্দিষ্ট ওয়ার্ডে কত সময় ব্যয় করেছিলেন। অর্থাৎ আমি একই ওয়ার্ডের মধ্যে টানা সময় কাটিয়েছি তার মোট সময়কাল জানতে চাই।

পরীক্ষা ক্ষেত্রে

-- Let's assume that ward_id = 1 corresponds to ICU (Intensive Care Unit)
INSERT INTO t
  (patient_id, bed_id, ward_id, admitted, discharged)
VALUES

-- Patient 1 is in ICU, changes some beds, then he is moved 
-- out of ICU, back in and finally he is out.
(1, 1, 1, '2015-01-06 06:05:00', '2015-01-07 06:04:00'),
(1, 2, 1, '2015-01-07 06:04:00', '2015-01-07 07:08:00'),
(1, 1, 1, '2015-01-07 07:08:00', '2015-01-08 08:11:00'),
(1, 4, 2, '2015-01-08 08:11:00', '2015-01-08 09:11:00'),
(1, 1, 1, '2015-01-08 09:11:00', '2015-01-08 10:11:00'),
(1, 3, 1, '2015-01-08 10:11:00', '2015-01-08 11:11:00'),
(1, 1, 2, '2015-01-08 11:11:00', '2015-01-08 12:11:00'),

-- Patient 2 is out of ICU, he gets inserted in ICU, 
-- changes some beds and he is back out
(2, 1, 2, '2015-01-06 06:00:00', '2015-01-07 06:04:00'),
(2, 1, 1, '2015-01-07 06:04:00', '2015-01-07 07:08:00'),
(2, 3, 1, '2015-01-07 07:08:00', '2015-01-08 08:11:00'),
(2, 1, 2, '2015-01-08 08:11:00', '2015-01-08 09:11:00'),

-- Patient 3 is not inserted in ICU
(3, 1, 2, '2015-01-08 08:10:00', '2015-01-09 09:00:00'),
(3, 2, 2, '2015-01-09 09:00:00', '2015-01-10 10:01:00'),
(3, 3, 2, '2015-01-10 10:01:00', '2015-01-11 12:34:00'),
(3, 4, 2, '2015-01-11 12:34:00', NULL),

-- Patient 4 is out of ICU, he gets inserted in ICU without changing any beds
-- and goes back out.
(4, 1, 2, '2015-01-06 06:00:00', '2015-01-07 06:04:00'),
(4, 2, 1, '2015-01-07 06:04:00', '2015-01-07 07:08:00'),
(4, 1, 2, '2015-01-07 07:08:00', '2015-01-08 09:11:00'),

-- Patient 5 is out of ICU, he gets inserted in ICU without changing any beds
-- and he gets dismissed.
(5, 1, 2, '2015-01-06 06:00:00', '2015-01-07 06:04:00'),
(5, 3, 2, '2015-01-07 06:04:00', '2015-01-07 07:08:00'),
(5, 1, 1, '2015-01-07 07:08:00', '2015-01-08 09:11:00'),

-- Patient 6 is inserted in ICU and he is still there
(6, 1, 1, '2015-01-11 12:34:00', NULL);

আসল সারণীতে সারিগুলি একটানা নয় তবে প্রতিটি রোগীর জন্য এক সারি থেকে স্রাবের টাইমস্ট্যাম্প == পরবর্তী সারির ভর্তির টাইমস্ট্যাম্প।

SQLFiddle

http://sqlfiddle.com/#!2/b5fe5

প্রত্যাশিত ফলাফল

আমি নিম্নলিখিত মত কিছু লিখতে চাই:

SELECT pid, ward_id, admitted, discharged
FROM  (....)
WHERE ward_id = 1;

(1, 1, '2015-01-06 06:05:00', '2015-01-08 08:11:00'),
(1, 1, '2015-01-08 09:11:00', '2015-01-09 11:11:00'),
(2, 1, '2015-01-07 06:04:00', '2015-01-08 08:11:00'),
(4, 1, '2015-01-07 06:04:00', '2015-01-07 07:08:00'),
(5, 1, '2015-01-07 07:08:00', '2015-01-08 09:11:00'),
(6, 1, '2015-01-11 12:34:00', NULL);

দয়া করে মনে রাখবেন যে আমরা রোগী_দিক দিয়ে গ্রুপ করতে পারি না। আমাদের অবশ্যই প্রতিটি আইসিইউ ভ্রমণের জন্য একটি পৃথক রেকর্ড পুনরুদ্ধার করতে হবে।

এটিকে আরও স্পষ্টভাবে বলতে গেলে, যদি কোনও রোগী আইসিইউতে সময় ব্যয় করে, তবে সেখান থেকে সরিয়ে নিয়ে আবার সেখানে ফিরে আসে, প্রতিটি আইসিইউ পরিদর্শনকালে তিনি মোট সময় ব্যয় করেছেন (যেমন দুটি রেকর্ড)


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

@ ভ্যারেস আমি কোড লিখতে বলেছি যা আইসিইউ বেডের সাথে সাদৃশ্যযুক্ত সমস্ত সারি পুনরুদ্ধার করে এবং আমি সেগুলিকে পাইথনে গ্রুপ করছি।
pmav99

অবশ্যই যদি এটি এসকিউএল এ তুলনামূলকভাবে পরিষ্কার উপায়ে করা যায় তবে আমি এটিকে পছন্দ করব।
pmav99

ভাষাগুলি যেতে যেতে পাইথন বেশ পরিষ্কার! :-) আপনি যদি মাইএসকিউএলে আটকে না থাকেন এবং আপনার যদি এফ / লসএস ডাটাবেসের প্রয়োজন হয় তবে আমি পোস্টগ্র্রেএসকিউএল (মাইএসকিউএল আইএমএইচওর চেয়ে অনেক উপায়ে উচ্চতর) সুপারিশ করতে পারি যার সিটিই এবং উইন্ডোভিং ফাংশন রয়েছে।
ভেরেস

উত্তর:


4

ক্যোয়ারী 1, এসকিউএলফিডাল -২ এ পরীক্ষিত

SET @ward_id_to_check = 1 ;

SELECT
    st.patient_id,
    st.bed_id AS starting_bed_id,          -- the first bed a patient uses
                                           -- can be omitted
    st.admitted,
    MIN(en.discharged) AS discharged
FROM
  ( SELECT patient_id, bed_id, admitted, discharged
    FROM t 
    WHERE t.ward_id = @ward_id_to_check
      AND NOT EXISTS
          ( SELECT * 
            FROM t AS prev 
            WHERE prev.ward_id = @ward_id_to_check
              AND prev.patient_id = t.patient_id
              AND prev.discharged = t.admitted
          )
  ) AS st
JOIN
  ( SELECT patient_id, admitted, discharged
    FROM t 
    WHERE t.ward_id = @ward_id_to_check
      AND NOT EXISTS
          ( SELECT * 
            FROM t AS next 
            WHERE next.ward_id = @ward_id_to_check
              AND next.patient_id = t.patient_id
              AND next.admitted = t.discharged
          )
  ) AS en
    ON  st.patient_id = en.patient_id
    AND st.admitted <= en.admitted
GROUP BY
    st.patient_id,
    st.admitted ;

ক্যোরি 2, যা 1 এর মতো তবে উত্পন্ন টেবিলগুলি ছাড়াই। এটির যথাযথ সূচী সহ সম্ভবত আরও কার্যকর সম্পাদনের পরিকল্পনা থাকবে। টেস্ট SQLFiddle-2 :

SET @ward_id_to_check = 1 ;

SELECT
    st.patient_id,
    st.bed_id AS starting_bed_id,
    st.admitted,
    MIN(en.discharged) AS discharged
FROM
    t AS st    -- starting period
  JOIN
    t AS en    -- ending period
      ON  en.ward_id = @ward_id_to_check
      AND st.patient_id = en.patient_id
      AND NOT EXISTS
          ( SELECT * 
            FROM t AS next 
            WHERE next.ward_id = @ward_id_to_check
              AND next.patient_id = en.patient_id
              AND next.admitted = en.discharged
          )
      AND st.admitted <= en.admitted
WHERE 
      st.ward_id = @ward_id_to_check
  AND NOT EXISTS
      ( SELECT * 
        FROM t AS prev 
        WHERE prev.ward_id = @ward_id_to_check
          AND prev.patient_id = st.patient_id
          AND prev.discharged = st.admitted
      )
GROUP BY
    st.patient_id,
    st.admitted ;

উভয় প্রশ্নই ধরে নেয় যে এখানে একটি অনন্য বাধা রয়েছে (patient_id, admitted)। যদি সার্ভারটি কঠোর এএনএসআই সেটিংস দিয়ে চলে, bed_idতবে GROUP BYতালিকাটিতে যুক্ত করা উচিত ।


নোট করুন যে আমি
ফ্রেডিতে

2
বিস্ময়ে - আমি সত্যিই ভেবেছিলাম যে সিটিইর অভাবে এটি অসম্ভব। আশ্চর্যজনকভাবে, প্রথম কোয়েরিটি এসকিউএলফিডেলে আমার জন্য চালিত হবে না - একটি ত্রুটি? দ্বিতীয়টি যদিও করেছে তবে আমি পরামর্শ দিচ্ছি যে st.bed_id মুছে ফেলা হবে, কারণ এটি বিভ্রান্তিকর। রোগী 1 তার প্রথম থাকার সমস্ত অংশ একই বিছানার 1 নং ওয়ার্ডে কাটেনি।
ভেরেস

@ ভেরেস, থানেক্স প্রথমে, আমি ভেবেছিলাম, আমাদের পুনরাবৃত্ত সিটিই দরকার needed আমি রোগী_আইডিতে একটি অনুপস্থিত যোগদান সংশোধন করেছি (এটি কারও নজরে নেই;) এবং বিছানা সম্পর্কে আপনার বক্তব্য যোগ করেছেন।
ypercubeᵀᴹ

@ টাইপ्यूब আপনার উত্তরের জন্য আপনাকে অনেক ধন্যবাদ! এটি সত্যই সহায়ক। আমি এটি বিস্তারিতভাবে অধ্যয়ন করতে যাচ্ছি :)
pmav99

0

প্রস্তাবিত QUERY

SELECT patient_id,SEC_TO_TIME(SUM(elapsed_time)) elapsed
FROM (SELECT * FROM (SELECT patient_id,
UNIX_TIMESTAMP(IFNULL(discharged,NOW())) -
UNIX_TIMESTAMP(admitted) elapsed_time
FROM t WHERE ward_id = 1) AA) A
GROUP BY patient_id;

আমি আমার ল্যাপটপের একটি স্থানীয় ডাটাবেসে আপনাকে নমুনা ডেটা লোড করেছি। তারপরে, আমি কোয়েরিটি চালিয়েছি

প্রস্তাবিত QUERY কার্যকর করা হয়েছে

mysql> SELECT patient_id,SEC_TO_TIME(SUM(elapsed_time)) elapsed
    -> FROM (SELECT * FROM (SELECT patient_id,
    -> UNIX_TIMESTAMP(IFNULL(discharged,NOW())) -
    -> UNIX_TIMESTAMP(admitted) elapsed_time
    -> FROM t WHERE ward_id = 1) AA) A
    -> GROUP BY patient_id;
+------------+-----------+
| patient_id | elapsed   |
+------------+-----------+
|          1 | 76:06:00  |
|          2 | 26:07:00  |
|          4 | 01:04:00  |
|          5 | 26:03:00  |
|          6 | 118:55:48 |
+------------+-----------+
5 rows in set (0.00 sec)

mysql>

প্রস্তাবিত QUERY বর্ণিত

সাবএকিয়ার এএ-তে, আমি ইউএনআইএক্স_টাইমস্ট্যাম্প () ব্যবহার করে বিভ্রান্ত হওয়া সেকেন্ডের সংখ্যাটি UNIX_TIMESTAMP(discharged)FROM বিয়োগ করে গণনা করি UNIX_TIMESTAMP(admitted)। যদি রোগী এখনও বিছানায় থাকে (যেমন স্রাবের দ্বারা চিহ্নিত করা হয় NULL), আমি এখনই সময় নির্ধারণ করি () । তারপরে, আমি বিয়োগফলটি করি। এটি আপনাকে ওয়ার্ডে থাকা যে কোনও রোগীর জন্য এক মিনিটের এক মিনিটের সময়সীমা দেবে।

তারপরে, আমি দ্বারা সেকেন্ডের সমষ্টি সংগ্রহ করি patient_id। অবশেষে, আমি প্রতিটি রোগীর জন্য সেকেন্ড সময় নিই এবং রোগীর থাকার সময়, মিনিট এবং কয়েক সেকেন্ড প্রদর্শন করতে SEC_TO_TIME () ব্যবহার করি

একবার চেষ্টা করে দেখো !!!


রেকর্ডের জন্য, আমি এটি আমার উইন্ডোজ 7 ল্যাপটপের মাইএসকিউএল 5.6.22 এ চালিয়েছি। এটি এসকিউএল ফিডেলে একটি ত্রুটি দেয়।
RolandoMySQLDBA

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

ভিন্ন বিষয়ে, আপনার (মূল) উত্তরের প্রতিবেদনটি আমি মনে করি যে দুটি সাবকিউয়েরি ব্যবহার করা সত্যই প্রয়োজনীয় নয় (যেমন টেবিল Aএবং AA)। আমি মনে করি যে তাদের মধ্যে একটি যথেষ্ট।
pmav99
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.