iT邦幫忙

0

SQL問題請教

是這樣的最近想做一種查詢內容大概是
我想做一種查詢,查2018/08/11~2018/11/11的全部資料
資料裡有身高、體重、BMI等等資料
如果說沒有資料沒變動,就只顯示一筆,有變動就顯示變動的那一筆
像這樣:
2018/08/11 身高180 體重:60 BMI:20
2018/09/11 身高180 體重:60 BMI:20

如果都沒變動只顯示最初的那筆,若有變動就顯示最初的那筆跟異動的那筆
目前我可以全部顯示出來跟選擇資料顯示的範圍,但這個我目前還沒頭緒,希望能有個方
向,謝謝。

小魚 iT邦高手 1 級 ‧ 2018-11-18 18:26:41 檢舉
後端處理會比較容易
tenno081 iT邦新手 5 級 ‧ 2018-11-18 18:37:04 檢舉
對,我的是asp.net mvc,我用的是linq的語法,因為我覺得這應該算查詢的部分,所以正在想該怎麼做
1
a4027971
iT邦新手 5 級 ‧ 2018-11-18 20:32:45
最佳解答

如果table schema (簡化只記錄 身高和體重)(BMI用算的不紀錄)

CREATE TABLE HEALTH_LOG(
    id integer,
    name text,
    height integer,
    weight integer
);

放入6筆資料

INSERT INTO HEALTH_LOG VALUES(1,'Tom', 170, 50);
INSERT INTO HEALTH_LOG VALUES(1,'Tom', 170, 50);
INSERT INTO HEALTH_LOG VALUES(1,'Tom', 171, 50);
INSERT INTO HEALTH_LOG VALUES(1,'Tom', 171, 51);
INSERT INTO HEALTH_LOG VALUES(1,'Tom', 171, 52);
INSERT INTO HEALTH_LOG VALUES(1,'Tom', 171, 52);

撈出 體重+身高不同(代表資料有變動)的rows

SELECT DISTINCT (height+weight), * 
FROM HEALTH_LOG
WHERE id = 1;

結果 (程式再取你要的欄位就好)


體重+身高 id 姓名 身高 體重
220 1 Tom 170 50
221 1 Tom 171 50
222 1 Tom 171 51
223 1 Tom 171 52
看更多先前的回應...收起先前的回應...
tenno081 iT邦新手 5 級 ‧ 2018-11-18 21:53:32 檢舉

原來是用這個,都忘了這個語法了,真的很感謝。

tenno081 iT邦新手 5 級 ‧ 2018-11-19 15:31:33 檢舉

您好,不知道您是否會linq語法?我的語法目前是這樣

 public List<HDOrderDto> FindHistory(string pat_guid,DateTime startDate, DateTime endDate)
        {
          var query = (from x in _repo.HD_ORDER
                         where x.PAT_GUID == pat_guid && x.ODR_DATE >= startDate && x.ODR_DATE <= endDate
                         orderby (x.ODR_DATE) descending
                         select new HDOrderDto
                         {
                             HDType = x.HD_TYPE,
                             OdrDate = x.ODR_DATE,
                             DryWtDesc = x.DRY_WT_DESC,
                             DryWtReasonDesc = x.DRY_WT_REASON_DESC
                         })ToList<HDOrderDto>();
         }        

加了distinct後

  public List<HDOrderDto> FindHistory(string pat_guid,DateTime startDate, DateTime endDate)
        {
         
            if (String.IsNullOrWhiteSpace(pat_guid)) return null;
            var query = (from x in _repo.HD_ORDER
                         where x.PAT_GUID == pat_guid && x.ODR_DATE >= startDate && x.ODR_DATE <= endDate                                        
                         select new HDOrderDto
                         {
                             HDType = x.HD_TYPE,
                             OdrDate = x.ODR_DATE,
                             DryWtDesc = x.DRY_WT_DESC,
                             DryWtReasonDesc = x.DRY_WT_REASON_DESC
                         }).Distinct().OrderByDescending(x=>x.OdrDate).ToList<HDOrderDto>();
            return query;             
        }

這樣好像無法完全消除掉重複的欄位,例如DryWtDesc這個欄位
我有找到一個網站,不知是否是這樣解
http://andy51002000.blogspot.com/2017/04/c-linq.html
最下面那個就是我想呈現的,只是我用的是linq+MVC
所以我不太清楚那個foreach該怎麼下,想請問是這樣解嗎?

a4027971 iT邦新手 5 級 ‧ 2018-11-20 10:46:11 檢舉

C#語法我本身不太熟
我不太清楚他的function最後把SQL包裝成什麼樣子
如果能看到它原始的SQL,可以知道問題

tenno081 iT邦新手 5 級 ‧ 2018-11-20 11:46:00 檢舉

了解,還是感謝。

1
rogeryao
iT邦研究生 5 級 ‧ 2018-11-18 20:12:27

MSSQL:
1.假設同一 UserID 同一天只有一筆資料
2.如果都沒變動只顯示最初的那筆,<==(顯示:最初的那筆)
若有變動就顯示最初的那筆跟異動的那筆 <==(顯示:最初的那筆及最後一次異動的那筆)

CREATE TABLE UserData(UserId VARCHAR(7),ModiDate DATE,High FLOAT,Weight FLOAT,BMI FLOAT);
INSERT INTO UserData(UserId,ModiDate,High,Weight,BMI)
VALUES
('A','2018/08/11',180,60,20),
('A','2018/09/11',180,60,20),
('A','2018/10/11',185,65,25),
('B','2018/11/11',190,70,30);


SELECT A.UserId,CONVERT(VARCHAR,A.ModiDate,111) AS ModiDate,A.High,A.Weight,A.BMI
FROM UserData AS A
INNER JOIN (
SELECT X.UserID,MAX(X.ModiDate) as MAXModiDate
FROM UserData AS X
WHERE 1=1
AND ModiDate BETWEEN '2018/08/11' AND '2018/11/11'
GROUP BY X.UserID
) AS B ON B.UserId=A.UserId AND B.MAXModiDate=A.ModiDate
UNION
SELECT C.UserId,CONVERT(VARCHAR,C.ModiDate,111) AS ModiDate,C.High,C.Weight,C.BMI
FROM UserData AS C
INNER JOIN (
SELECT Y.UserID,MIN(Y.ModiDate) as MINModiDate
FROM UserData AS Y
WHERE 1=1
AND ModiDate BETWEEN '2018/08/11' AND '2018/11/11'
GROUP BY Y.UserID
) AS D ON D.UserId=C.UserId AND D.MINModiDate=C.ModiDate
ORDER BY UserId,ModiDate


https://dbfiddle.uk/?rdbms=sqlserver_2017&fiddle=0cd11ce21a00d9d31fb680deaf0e4643

圓頭人 iT邦新手 3 級 ‧ 2018-11-19 10:02:33 檢舉

大大高招,謝謝大大
取最大 union 取最小 如果沒有變更,就會union成一筆

select * from UserData a  where  ModiDate = (select max(x.ModiDate) from UserData x where x.UserID = a.UserID)
union
select * from UserData a  where  ModiDate = (select min(x.ModiDate) from UserData x where x.UserID = a.UserID)
0
froce
iT邦高手 1 級 ‧ 2018-11-18 21:45:45

不知道C#有沒有set,要是我的話就對所有資料取出來做set,然後取最後一筆就好。

我要發表回答

立即登入回答