Я делал множество sql-запросов с левыми соединениями на протяжении многих лет, но никогда не видел этого, и я не могу найти по нему никакой информации.

Начнем с запроса

SELECT Services.rn AS srn, Address_Id, Customer_Id, Service_Id, Next_Service, Next_End, Confirmed, Address, First_Name, Last_Name, Company, Service_Type, City
FROM `Services`
LEFT JOIN
    (SELECT rn, Address, City_Id FROM `Service_Address`) AS saddresss ON saddresss.rn = Services.Address_Id
LEFT JOIN
    (SELECT rn, First_Name, Last_Name, Company FROM `Customer`) AS customer ON customer.rn = Services.Customer_Id
LEFT JOIN
    (SELECT rn, Service_Type FROM `Service_Desc`) AS servdesc ON servdesc.rn = Services.Service_Id
LEFT JOIN
    (SELECT rn, City FROM `City_List`) AS city ON city.rn = saddresss.City_Id
WHERE `Services`.`Next_Service` BETWEEN " . $daystart . " AND " . $dayend . "
ORDER BY `Services`.`Customer_Id` ASC, `Services`.`Address_Id` ASC, `Services`.`rn` ASC

Единственное, что не указано выше, - это переменные $ daystart и $ dayend, и это просто временные метки unix.

Обычно я затем использую цикл while для обработки результатов.

while ($row = $res->fetch_assoc())
{
    //do something here
}

Но когда я получил пустой результат, я решил отладить с помощью var_dump. Если вы var_dump «$ row» вы получите массив, то же самое, если вы var_dump «$ res-> fetch_assoc ()». Но не в этот раз, если я var_dump "$ res-> fetch_assoc ()" я получаю массив, но если я var_dump "$ row", я получаю "bool (true)" для каждой "строки". И если попытаться повторить какое-либо из значений в "$ row" ($ row ['City']), я ничего не получу.

Очевидно, что результаты есть, поскольку var_dump "$ res-> fetch_assoc ()" показывает массив, и в нем есть правильные данные, но я понятия не имею, как я к нему подхожу, поэтому я могу его отобразить.

РЕДАКТИРОВАТЬ:

Я забыл упомянуть, что я выполнил запрос в phpmyadmin, заменив только $ daystart на 1456207200 и $ dayend на 1456293599, и он работает. Не уверен, почему это не работает в PHP

РЕДАКТИРОВАТЬ 2:

На основе моего второго комментария к сообщению DRapp. Я подумал, может быть, будет полезна структура таблицы «Услуги».

CREATE TABLE IF NOT EXISTS `Services` (
  `rn` int(10) NOT NULL,
  `Customer_Id` int(10) NOT NULL,
  `Address_Id` int(10) NOT NULL,
  `Service_With` int(10) NOT NULL,
  `Service_Id` int(5) NOT NULL,
  `Service_Desc` varchar(200) COLLATE utf8mb4_unicode_520_ci NOT NULL,
  `Initial_Service` int(10) NOT NULL,
  `Last_Service` int(10) NOT NULL,
  `Next_Service` int(10) NOT NULL,
  `Next_End` int(10) NOT NULL,
  `Confirmed` int(1) NOT NULL,
  `Product_Quantity` int(5) NOT NULL,
  `Product_Rate` double(6,2) NOT NULL,
  `Charge` double(6,2) NOT NULL,
  `Fequency_Id` int(5) NOT NULL,
  `Route` int(5) NOT NULL,
  `Salesman` int(5) NOT NULL,
  `Warranty_Expires` int(5) NOT NULL,
  `Canceled` int(10) NOT NULL DEFAULT '0',
  `Cancel_Reason` varchar(200) COLLATE utf8mb4_unicode_520_ci NOT NULL,
  `Office_Note` text COLLATE utf8mb4_unicode_520_ci NOT NULL,
  `Customer_Note` text COLLATE utf8mb4_unicode_520_ci NOT NULL,
  `Technician_Note` text COLLATE utf8mb4_unicode_520_ci NOT NULL
) ENGINE=InnoDB AUTO_INCREMENT=4651 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_520_ci;
0
Krik 24 Фев 2016 в 05:13

2 ответа

Лучший ответ

После получения моего запроса

SELECT *
FROM Services
WHERE Next_Service >=  $daystart AND Next_Service <= $dayend

И затем, глядя на него в течение 30 минут, чтобы увидеть, есть ли какой-либо дефект, я начал подозревать мой PHP как виновник. Цикл while, который я предоставил в своем OP, является примером моего цикла while по умолчанию для обработки результатов запроса. Проблема в том, что в этом случае я подумал сделать быстрый ярлык, чтобы избежать лишнего оператора «если». Мой цикл while на самом деле выглядит примерно так

while ($row = $res->fetch_assoc() && $somevalue != '')
{
    //do something here
}

И, если вы знаете что-нибудь о синтаксисе, если "$ somevalue" не было пустым, для "$ row" было бы установлено значение "bool (true)".

Просто хотел поблагодарить DRapp за его усилия, я бы принял ваш ответ, если бы мог, но поскольку проблема не связана с какой-либо предоставленной информацией, я уверен, что она не сработает с SO. Это был один из тех моментов, о, черт возьми, я должен признать, что даже не решался публиковать, так как он почти достигает рейтинга с такими ошибками, как забывание точки с запятой (;). Но надеюсь, это кому-то поможет.

0
Krik 24 Фев 2016 в 20:00

Вот вам очищенный SQL-запрос без надлежащих кавычек, но с сохранением параметров для вас. Выборы LEFT-JOIN были бесполезны для добавления в запрос ненужных слоев.

Я упростил ссылки на псевдонимы и, надеюсь, имеет для вас больше смысла. Для выполнения запросов я пытаюсь начать с предложения FROM и идентифицировать все объединения и то, как каждая таблица напрямую связана, чтобы получить все поля по мере необходимости. На этом этапе не беспокойтесь о критериях, а только о том, КАК они связаны. Я также всегда стараюсь указать ПЕРВУЮ таблицу слева от предложения ON для соединения и справа от той, к которой присоединяется. Кроме того, в случае, если службы присоединены к адресу службы, а затем адрес службы к списку городов, обратите внимание, как я сделал их отступом ... Это имеет прямой смысл, какие ссылки на что, вместо того, чтобы просто помещать куда-либо и надеяться, что никто после вас нужно во всем разобраться. Также проще, если вам придется вернуться к нему позже.

SELECT 
      S.rn AS srn, 
      S.Address_Id, 
      S.Customer_Id, 
      S.Service_Id, 
      S.Next_Service, 
      Next_End, 
      Confirmed, 
      SvcAdr.Address, 
      Cst.First_Name, 
      Cst.Last_Name, 
      Cst.Company, 
      SD.Service_Type, 
      C.City
   FROM 
      Services AS S
         LEFT JOIN Service_Address AS SvcAdr
            ON S.Address_Id = SvcAdr.rn
            LEFT JOIN City_List AS C
               ON SvcAdr.City_Id = city.rn
         LEFT JOIN Customer  AS Cst
            ON Services.Customer_Id = Cst.rn 
         LEFT JOIN Service_Desc AS SD
            ON S.Service_Id = SD.rn
   WHERE 
      S.Next_Service BETWEEN  $daystart AND  $dayend 
   ORDER BY 
      S.Customer_Id ASC, 
      S.Address_Id ASC, 
      S.rn ASC

Что касается того, что он не работает через PHP, это может быть совпадением, но также старайтесь всегда квалифицировать свои поля с помощью правильной таблицы (или псевдонима), а не угадывать.

И последнее замечание о датах обслуживания, и похоже, что вы используете временную метку на основе UNIX. Я хотел бы убедиться, что начало основано на 12:00:00 (полночь) в начале и в 23:59:59 в последнюю дату, чтобы вы не пропустили ничего, что могло бы быть серединой дня соответствующего начала / даты окончания.

< Сильный > ОБРАТНОЙ

Тогда мое предложение. Начните ТОЛЬКО с запроса служб, затем добавляйте по одному LEFT-JOIN за раз. Услуги, просто выберите свой диапазон дат. Если ничего не возвращается, вы знаете свой тост за ворота. Кроме того, поскольку вы выполняете LEFT-JOINs, вы можете применить ex: COALESCE (SvcAdr.Address, "") в качестве адреса, чтобы предотвратить возвращение нулей.

Начать с

SELECT 
      S.rn AS srn, 
      S.Address_Id, 
      S.Customer_Id, 
      S.Service_Id, 
      S.Next_Service, 
   FROM 
      Services AS S
   WHERE 
      S.Next_Service BETWEEN  $daystart AND  $dayend 
1
DRapp 24 Фев 2016 в 03:53