Как я включаю пустые строки в единственный ДЕНЬ GROUP BY (date_field) SQL-запрос?

Я действительно сталкивался с этой проблемой прежде, и есть существенные осложнения.

Во-первых, может очень легко потерять доступ к значению «this», поэтому вы должны быть осторожны. Альтернатива состоит в том, чтобы рассматривать каждую функцию как статический, чистый метод, который просто определен в объекте. Второй - это порядок оценки декораторов, который, как вы, вероятно, уже знаете, вывернут наизнанку.

1113 Учитывая это, я и сделал. Я использовал этот код с Meteor, который сделал нечто очень похожее на то, что вы делаете.

Преамбула

ServerModule был просто классом с серией обработчиков методов. AKA контроллер, и этот код был построен для Meteor.

Код

/**
 * This is horribly ugly code that I hate reading myself, 
 * but it is very straightforward. It defines a getter
 * property called __modulle, and returns the data that
 * we care about in a format that is readable for a future
 * registry/bootstrapping system
 */
function boltModuleProperty(proto: any) {
  Object.defineProperty(proto, '__module', {
    get: function () {
      let obj: IModuleDetails = {};
      for (let key in this.__moduleFunctions)
        obj[`${this.__moduleName}.${key}`] = this.__moduleFunctions[key];
      return obj;
    }
  })
}

/**
 * This is evaluated at the very end.
 * 
 * Collect all the methods and publications, registering
 * them with Meteor so they become available via the
 * default Meteor Methods and Subscriptions.
 */
export function ServerModule (moduleName?: string) {
  return function (target: any) {
    boltModuleProperty(target.prototype);
    // Use either a passed-in name, or the class' name
    target.prototype.__moduleName = moduleName || target.name;
  }
}


/**
 * Take the name of the method to be exposed for Meteor,
 * and save it to the object's prototype for later. We
 * we do this so we can access each method for future 
 * registration with Meteor's 'method' function
 */
export function ServerMethod (name: string = null) {
  return function (target: any, propertyKey: string, descriptor: PropertyDescriptor) {
    let fnName = name || descriptor.value.name;
    // ensure we actually get the real prototype
    let proto = target.prototype ? target.prototype : target.constructor.prototype 

    if (!proto.__moduleFunctions) proto.__moduleFunctions = {};
    proto.__moduleFunctions[fnName] = descriptor.value;
  }
}

Пояснение

Вы определяете дополнительную информацию о классе в формате, который вы можете читать и понимать. Каждый метод / свойство, которое вы используете внутри класса, должен хранить информацию о себе, и НЕ выполнять ЛЮБЫЕ действия. Декоратор никогда не должен вызывать какого-либо внешнего побочного эффекта , когда-либо . Я только делаю это важным моментом, потому что вы не хотите забывать о том, как все происходит в вашей кодовой базе.

Теперь, когда у нас есть некоторый код для просмотра, мы должны обойти эту надоедливую регистрацию и не потерять доступ к некоторому потенциально связанному коду. У нас есть все, что нам нужно, через вновь созданное свойство __module класса, но оно пока не видно в машинописи.

Здесь есть два варианта:

let myInstance: IServerModule & MyClass = new MyClass();
// or
let myInstance: any = new MyClass();

Настройка

Однако, при доступе к регистрации метода (express.get и т. Д.), Вам нужно что-то, что требует ссылка на класс, сохраняет его в реестре (буквально просто массив в некотором загрузочном файле, похожем на модули Angular) и регистрирует все в этом загрузочном / модульном файле.

Откройте свойство __module, прочитайте информацию, которую вы сохранили, и зарегистрируйте ее при необходимости. Таким образом, вы выполняете разделение задач, у вас есть четкое понимание того, что создается в вашем приложении, и вы можете использовать свои декораторы именно так, как считаете нужным.

5
задан Jonathan Leffler 7 September 2013 в 23:12
поделиться

4 ответа

Как насчет чего-то вроде этого?

SELECT 
  COUNT(incident_id) AS "Calls",
  MAX(open_time),
  days.open_day
FROM
(
  select datepart(dd,dateadd(day,-6,getdate())) as open_day union
  select datepart(dd,dateadd(day,-5,getdate())) as open_day union
  select datepart(dd,dateadd(day,-4,getdate())) as open_day union
  select datepart(dd,dateadd(day,-3,getdate())) as open_day union
  select datepart(dd,dateadd(day,-2,getdate())) as open_day union
  select datepart(dd,dateadd(day,-1,getdate())) as open_day union
  select datepart(dd,dateadd(day, 0,getdate())) as open_day 
) days
left join 
(
 SELECT
   incident_id,
   opened_by,
   open_time - (9.0/24) AS open_time,
   DATEPART(dd, (open_time-(9.0/24))) AS open_day
 FROM incidentsm1 
 WHERE DATEDIFF(DAY, open_time-(9.0/24), GETDATE()) < 7
) inc1 ON days.open_day = incidents.open_day
GROUP BY days.open_day

Я только протестировал его на упрощенной схеме таблицы, но я думаю, что это должно работать. Вы, возможно, должны были бы переделать материал dateadd..

7
ответ дан 14 December 2019 в 09:02
поделиться

Я предложил бы использование таблицы даты. С существующей таблицей даты на месте, можно выполнить ПРАВИЛЬНОЕ ВНЕШНЕЕ ОБЪЕДИНЕНИЕ к таблице даты для введения недостающих дней.

0
ответ дан 14 December 2019 в 09:02
поделиться

Можно ли создать набор дат как часть запроса? Что-то вроде:

SELECT COUNT(*) AS Calls, ...
    FROM incidentsm1 RIGHT OUTER JOIN
         (SELECT date_values
            FROM TABLE(('27 Feb 2009'), ('28 Feb 2009'), ('1 Mar 2009'),
                       ('2 Mar 2009'), ('3 Mar 2009'), ('4 Mar 2009'),
                       ('5 Mar 2009')) AS date_list
         )
         ON ...

Это вдохновлено своего рода гибридом Informix и нотаций DB2 и, как в значительной степени гарантируют, будет синтаксически неправильно в обоих. В основном есть ли путь в Вашем DBMS составления литеральной таблицы на лету. Одна возможность - ужасный, но едва выполнимый - состояла бы в том, чтобы сделать ОБЪЕДИНЕНИЕ с 7 путями литералов даты, выбранных из 'двойного' или некоторого выражения таблицы, которое гарантирует одну строку (в терминах Informix, SELECT MDY(2,28,2009) FROM "informix".systables WHERE tabid = 1 UNION ...).

0
ответ дан 14 December 2019 в 09:02
поделиться

Можно ли создать табличную переменную с датами, в которых Вы нуждаетесь и затем RIGHT JOIN на него? Например,

DECLARE @dateTable TABLE ([date] SMALLDATETIME)

INSERT INTO @dateTable
VALUES('26 FEB 2009')
INSERT INTO @dateTable
VALUES('27 FEB 2009')
-- etc

SELECT 
  COUNT(*) AS "Calls",
  MAX(open_time),
  open_day
FROM 
  (
SELECT
 incident_id,
 opened_by,
 open_time - (9.0/24) AS open_time,
 DATEPART(dd, (open_time-(9.0/24))) AS open_day
   FROM incidentsm1
   RIGHT JOIN @dateTable dates
   ON incidentsm1.open_day = dates.date
   WHERE 
 DATEDIFF(DAY, open_time-(9.0/24), GETDATE())< 7

  ) inc1
GROUP BY open_day

Более идеальная ситуация однако, должен был бы иметь объект таблицы с датами в

0
ответ дан 14 December 2019 в 09:02
поделиться
Другие вопросы по тегам:

Похожие вопросы: