У меня есть таблица, в которую я вставляю значения, связанные с идентификатором, которые меняются со временем.

Пример:

| Id  |         Timestamp         |  Value  |
|  1  |  2018-09-12 02:29:31.154  |   7.139 |
|  1  |  2018-09-12 02:40:46.724  |   7.254 |
|  2  |  2018-09-06 02:40:46.724  | 132.451 |
|  1  |  2018-09-12 02:42:19.841  |   7.645 |
|  3  |  2018-09-12 03:01:45.811  |  45.276 |
|  1  |  2018-09-12 03:12:59.121  |   7.421 |
|  2  |  2018-09-12 03:12:59.121  | 130.789 |
|  1  |  2018-09-12 03:15:33.467  |   7.121 |
|  2  |  2018-09-12 03:15:33.467  | 136.198 |
|  3  |  2018-09-12 03:15:33.467  |  46.971 |
|  2  |  2018-09-12 03:27:13.642  | 131.879 |
|  3  |  2018-09-12 03:27:13.642  |  44.645 |
|  1  |  2018-09-12 03:30:27.564  |   7.691 |
| ... |            ...            |   ...   |

Моя цель - сделать один запрос, чтобы брать значения между диапазоном дат для Id 1, 2 и 3 и соединять их вместе.

Результат будет примерно таким:

{ Timestamp: "2018-09-12 02:29:31.154", id1: 7.123, id2: null, id3: null }
{ Timestamp: "2018-09-12 02:40:46.724", id1: 7.254, id2: 132.451, id3: null }
{ Timestamp: "2018-09-12 02:42:19.841", id1: 7.645, id2: null, id3: null }
{ Timestamp: "2018-09-12 03:01:45.811", id1: null, id2: null, id3: 45.276 }
{ Timestamp: "2018-09-12 03:12:59.121", id1: 7.421, id2: 130.789, id3: null }
{ Timestamp: "2018-09-12 03:15:33.467", id1: 7.121, id2: 136.198, id3: 46.971 }
{ Timestamp: "2018-09-12 03:27:13.642", id1: null, id2: 131.879, id3: 44.645 }
{ Timestamp: "2018-09-12 03:30:27.564", id1: 7.691, id2: null, id3: null }


Возможно ли это в одном запросе?

0
Broge 13 Сен 2018 в 10:03

2 ответа

Лучший ответ
var ids = new List<int> { 1, 2, 3};

var result = (from item in db.Table
              where ids.Contains(item.id) && item.Timestamp > fromDate && item.Timestamp < toDate
              group item by item.Timestamp into sub
              select new 
              {
                  Timestamp = sub.Key,
                  id1 = sub.Where(x => x.id == 1).Select(x => x.Value).FirstOrDefault(),
                  id2 = sub.Where(x => x.id == 2).Select(x => x.Value).FirstOrDefault(),
                  id3 = sub.Where(x => x.id == 3).Select(x => x.Value).FirstOrDefault()
              }).ToList();
1
Slava Utesinov 13 Сен 2018 в 07:36

Как насчет использования агрегирования строк в SQL Server 2017 с использованием функции STRING_AGG() [документация] он будет работать следующим образом:

SELECT [Timestamp]
  -- building string very similar to what you've posted; you can certainly play with this column and format it the way you want
  , STRING_AGG(CONCAT('id', CAST(Id AS nvarchar(50)), ': ', ISNULL(CAST([Value] AS nvarchar(50)), N'NULL')), ', ')
FROM schema.Table
GROUP BY [Timestamp];

Если вы используете старую версию SQL Server, логика будет такой же, вы просто прибегнете к индивидуальному способу агрегирования строк, например к одному из следующих:

Я сам обычно использую решение XML, когда STRING_AGG() недоступен.

0
MK_ 13 Сен 2018 в 07:43