торт PHP 3 - Как получить подзапросы в разделе SELECT - PullRequest
0 голосов
/ 19 марта 2020

Есть ли у кого-нибудь предложения или опыт, как выполнить подзапрос в SELECT, который напрямую зависит от значений в полях основного запроса в Cake PHP 3? Запрос показан ниже.

Я пытаюсь получить значение OnHand для каждого предмета на каждом складе. Мой список предметов и складов будет динамичным c. Некоторые пользователи могут видеть до 12 складов и 2K-3K товаров. С моим запросом в SQL я могу получить массив элементов, каждый из которых содержит 3 - 12 элементов. Хороший массив для легкого зацикливания в целях отображения.

Мой запрос действителен для SQL. Я получаю около 200 результатов. Я уверен, что я построил подзапросы не так, как надо, но я не мог понять, как выполнить подзапрос в выбранной части моего запроса.

Теперь я понимаю, что проблема не в пагинации, а в ResultSet ( duh, в сообщении об ошибке говорится, что с самого начала ). Я попытался запрос без нумерации страниц. Я могу беспокоиться о нумерации страниц позже . Просто

$query = $this->Inventory->Products->find('all', ['fields' => $select, 'conditions' => $conditions, 'order' => [$sort => $direction]]);

$ query-> all (), $ query-> toList () и $ query-> first () генерируют одинаковую ошибку ResultSet.

Примеры в Cake PHP документация и большинство (если не все, . Я уверен, что пропустил некоторые ) из других примеров в стеке, показывают подзапросы в разделе запросов FROM или WHERE или при объединении между таблицами.

ИЛИ

Я поступаю неправильно? Могу ли я получить ту же идею о результатах в другом запросе?

Любая и вся помощь очень ценится. Спасибо.

Кроме того, спасибо @ndm за редактирование моего поста, чтобы сделать его более удобным для чтения. Вы должны были работать. :)

Среда:

  • Торт PHP 3.8.6
  • PHP 7.3.7
  • MS SQL 2014

код контроллера => индексный метод

debug($select); выход

[(int) 0 => 'Products.ItemCode',
(int) 1 => 'Products.ItemName',
''03'' => '(SELECT OnHand FROM OITW WHERE ItemCode = Products.ItemCode AND WhsCode = '03')',
''04'' => '(SELECT OnHand FROM OITW WHERE ItemCode = Products.ItemCode AND WhsCode = '04')',
''05'' => '(SELECT OnHand FROM OITW WHERE ItemCode = Products.ItemCode AND WhsCode = '05')',
''06'' => '(SELECT OnHand FROM OITW WHERE ItemCode = Products.ItemCode AND WhsCode = '06')',
''07'' => '(SELECT OnHand FROM OITW WHERE ItemCode = Products.ItemCode AND WhsCode = '07')',
''08'' => '(SELECT OnHand FROM OITW WHERE ItemCode = Products.ItemCode AND WhsCode = '08')',
''09'' => '(SELECT OnHand FROM OITW WHERE ItemCode = Products.ItemCode AND WhsCode = '09')',
''14'' => '(SELECT OnHand FROM OITW WHERE ItemCode = Products.ItemCode AND WhsCode = '14')',
''15'' => '(SELECT OnHand FROM OITW WHERE ItemCode = Products.ItemCode AND WhsCode = '15')']

debug($conditions); выход

['Products.validFor' => 'Y',
'Products.ItemCode LIKE ' => 'TCP%']
$this->paginate = [
    'fields' => $select,
    'conditions' => $conditions,
    'order' => [$sort => $direction]
]; 
$query = $this->Inventory->Products->find('all', $this->paginate);
debug($query);

выход

SELECT
    Products.ItemCode AS [Products__ItemCode],
    Products.ItemName AS [Products__ItemName],
    (SELECT OnHand FROM OITW WHERE ItemCode = Products.ItemCode AND WhsCode = '03') AS '03',
    (SELECT OnHand FROM OITW WHERE ItemCode = Products.ItemCode AND WhsCode = '04') AS '04', 
    (SELECT OnHand FROM OITW WHERE ItemCode = Products.ItemCode AND WhsCode = '05') AS '05', 
    (SELECT OnHand FROM OITW WHERE ItemCode = Products.ItemCode AND WhsCode = '06') AS '06', 
    (SELECT OnHand FROM OITW WHERE ItemCode = Products.ItemCode AND WhsCode = '07') AS '07', 
    (SELECT OnHand FROM OITW WHERE ItemCode = Products.ItemCode AND WhsCode = '08') AS '08', 
    (SELECT OnHand FROM OITW WHERE ItemCode = Products.ItemCode AND WhsCode = '09') AS '09', 
    (SELECT OnHand FROM OITW WHERE ItemCode = Products.ItemCode AND WhsCode = '14') AS '14', 
    (SELECT OnHand FROM OITW WHERE ItemCode = Products.ItemCode AND WhsCode = '15') AS '15' 
FROM
    OITM Products
WHERE
    (Products.validFor = :c0 AND Products.ItemCode like :c1) 
ORDER BY
    Products.ItemName ASC
$inventory = $this->paginate($query, ['limit' => 50]);
debug($inventory);

дает

Аргумент 1, передаваемый в Cake \ ORM \ Entity :: __ construct (), должен иметь массив типов, данный bool, вызванный в C: \ inetpub \ wwwroot \ vendor \ cakephp \ cakephp \ src \ ORM \ ResultSet. php в строке 602

1 Ответ

0 голосов
/ 21 марта 2020

Я попытался запечь подзапросы с помощью

$select[] = $this->Inventory->find()->select([$key => 'OnHand'])->where(['WhsCode' => $key, 'ItemCode' => 'Products.ItemCode']);

У меня не было особой надежды и, конечно, это не сработало, когда обрабатывался Products.ItemCode в виде строки вместо фактической таблицы и полей БД, когда Cake создал запрос. Перечитывание документации построителя запросов для Cake (, как предложено @ Salinas ) все еще приводило меня в тупик, поскольку в разделе подзапроса использовались объединения. В моем запросе и подзапросах нет соединений в этом конкретном запросе.

Наконец, я понял, что при двойном однократном заключении в кавычки псевдонима и значения кода хранилища при выполнении моего l oop складов. Первоначально я сделал это для того, чтобы код моего хранилища обрабатывался как строка. Поскольку я не видел двойных одинарных кавычек в debug(sql($query)), я не думал, что это проблема. Пример: $select["'".$key."'"] = "(SELECT OnHand FROM OITW WHERE ItemCode = Products.ItemCode AND WhsCode = '".$key."')"; Это то, что казалось проблемой с Cake ResultSet.

В конечном счете, вот мой l oop для создания подзапросов. Я предварительно добавил текст к псевдониму подзапроса и набрал приведенный код хранилища (потенциальные значения - все числа, но некоторые с нулевым префиксом). Я все еще думаю, что подзапрос мог / должен быть Caked, но так как этот вопрос, кажется, не вызывает чьего-либо интереса, я закрою его, когда решу свою проблему.

foreach($this->Inventory->coWrhs as $key => $val)
{
    //how about pre-prending something to the select key & try type casting WhsCode
    $select['whrs_'.$key] = "(SELECT OnHand FROM OITW WHERE ItemCode = Products.ItemCode AND WhsCode = ".(string)$key.")";
}

Поиск Cake (), включая массив $select для полей:

$query = $this->Inventory->Products->find('all', [
            'fields' => $select, 
            'conditions' => $conditions, 
            'order' => [$sort => $direction]
         ]);

Чтобы в конечном итоге создать этот запрос:

SELECT 
  Products.ItemCode AS [Products__ItemCode], 
  Products.ItemName AS [Products__ItemName], 
  (SELECT OnHand FROM OITW WHERE ItemCode = Products.ItemCode AND WhsCode = 03) AS [whrs_03], 
  (SELECT OnHand FROM OITW WHERE ItemCode = Products.ItemCode AND WhsCode = 04) AS [whrs_04], 
  (SELECT OnHand FROM OITW WHERE ItemCode = Products.ItemCode AND WhsCode = 05) AS [whrs_05], 
  (SELECT OnHand FROM OITW WHERE ItemCode = Products.ItemCode AND WhsCode = 06) AS [whrs_06], 
  (SELECT OnHand FROM OITW WHERE ItemCode = Products.ItemCode AND WhsCode = 07) AS [whrs_07], 
  (SELECT OnHand FROM OITW WHERE ItemCode = Products.ItemCode AND WhsCode = 08) AS [whrs_08], 
  (SELECT OnHand FROM OITW WHERE ItemCode = Products.ItemCode AND WhsCode = 09) AS [whrs_09], 
  (SELECT OnHand FROM OITW WHERE ItemCode = Products.ItemCode AND WhsCode = 14) AS [whrs_14], 
  (SELECT OnHand FROM OITW WHERE ItemCode = Products.ItemCode AND WhsCode = 15) AS [whrs_15] 
FROM 
  OITM Products 
WHERE 
    (Products.validFor = 'Y' AND Products.ItemCode like 'TCP%') 
ORDER BY 
  Products.ItemName ASC OFFSET 0 ROWS FETCH FIRST 50 ROWS ONLY

Простой l oop -подключаемый Caked ( несколько? ) объект массива с разбиением на страницы, построенный с подзапросами, напрямую зависящими от поля в первичном запросе.

...