м-да, посмотрела на него несколько дней ... пришла к выводу, что ключ, видимо, надо использовать составной из полей Товар-Дата (т к по первонач задаче даже в один день была закупка одного товара по разным ценам)... в любом случае, даже как найти TOP по дате в рамках КАЖДОЙ группы по Товару - осталось большой загадкой??... кроме как, я наконец, поняла 3 правила Нормализации Таблиц для БД (хорошо расписано здесь) и попробовала рисовать Схему (которая по данной задаче тоже осталась загадкой)?... вобщем, очень уж "не-релятивная" задача оказалась... но всё-таки как-то, наверно, здесь можно рассмотреть одну таблицу, 2 раза обозвав её в запросе по-разному, и 1-й раз) сделать выборку по Товар, Count (группа по Товар) - выделив уникальные (если DISTINCT не пройдёт); 2-й раз) выборку TOP 3 Дата ordered by desc... и тут я потеряла все отношения между данными ... не зная на предмет чего сравнивать дальше эти выборки, и понимая, что даты поставки у каждого товара свои... TOP потерялся... а было очень интересно реализовать что-то вроде (только не по max, а по top 3) - если бы подошло:
Цитата
...такой запрос требует соединения таблицы P1 с собой, чтобы можно было разделить ее на вложенную серию сгруппированных таблиц. После этого в каждой группе извлекается максимальное значение...
p.s. TheBest, но вам спасибо за наводку! (узнала новые слова)
чтобы не гадать на кофейной гуще, кто вам отвечает и после этого не совершать кучу ошибок - обратитесь к собеседнику на ВЫ - ответ на ваш вопрос получите - а остальное вас не касается (п.п.п. на форумах)
очень резкий разворот событий после нескольких дней попыток применить TOP... (open office не имею, чем файл ods открыть не знаю, переводить формулы для именованных диапазонов - могу застрять ещё надолго)... поэтому пока на скорую руку из ИСХОДНОГО ТЗ (данные, оставшиеся в пост№26) - не для больших выборок, но быстро (правда шагов несколько): 0) доп. столбец id по мм стекла (для фильтра потом) - конкретно для данного примера 1) Свести Среднее по дате (т к они повторялись для одного товара) - и по Товару в Сводной на лист PTdate_AVG 2) далее Сводную из (1) раскидать по фильтру -- (находясь в сводной): Параметры--Сводная Таблица--Параметры-- Отобразить страницы фильтра отчёта... 3) выбрать любой - взяла Лист 10 -- отсортировать Сводную на убывание 4) в столбце E:F применить формулы (по примеру на contextures.com) --> для отбора 1-ых 3-х из Сводной --> найти Среднее 5)меняя фильтр по мм стекла - видеть данные по каждому... - как альтернативный вариант (показался симпатичным)... (как свести все средние в одну таблицу, как хотелось ТС, - вариантов др, кроме уже данных, пока не вижу) p.s. решение из поста №26 через подключение - тоже оставлено в файле... для варианта, описанного в этом посте, оно не используется
чтобы не гадать на кофейной гуще, кто вам отвечает и после этого не совершать кучу ошибок - обратитесь к собеседнику на ВЫ - ответ на ваш вопрос получите - а остальное вас не касается (п.п.п. на форумах)
TheBestOfTheBest написал: Для последних 3-х дат могу предложить только сводную, пока.
видимо, что-то не совсем то - посмотрела на данных из файла№34 - что-то с сортировкой, наверно... т к по 10см даёт среднее между средними (первыми 3мя и последними 3мя)... экзотика... у меня -- методами google, проб, ошибок и адаптации -- пока только вариант среднего за последний день:
Код
SELECT t1.Товар, t1.Дата ,avg(t1.`Цена за ед без НДС`) as Стоимость FROM table1 t1
INNER JOIN (SELECT Товар, MAX(Дата) AS maxДата FROM table1 GROUP BY Товар) t2
ON (t2.Товар = t1.Товар and t2.maxДата = t1.Дата)
GROUP BY t1.Товар, t1.Дата
чтобы не гадать на кофейной гуще, кто вам отвечает и после этого не совершать кучу ошибок - обратитесь к собеседнику на ВЫ - ответ на ваш вопрос получите - а остальное вас не касается (п.п.п. на форумах)
TheBest, насколько вижу ваш запрос отбирает макс не нулевые, потом следущие макс из оставшихся, и снова следующие из оставшихся после второго отбора, после чего, наверно, формирует итоговую строку среднего через очередной LEFT JOIN и RIGHT JOIN... оказалось трудным уловить последовательность действий ваших операторов при отборе - если найдётся время пояснить, было бы очень познавательно... или может быть, схемой было бы понятнее?.. и интересно уточнить, конкретно по данному запросу вы делали вручную или VS или MS Query?.. (ваш опыт работы с запросами привносит много нового и полезного в мои мысли ) _________________________ у меня получился такой ход мыслей: ( отталкиваясь отсюда по 3-м последним) отбор 3-х макс Дат
Скрытый текст
Код
SELECT MAX(Дата) AS maxДата FROM table1
UNION ALL
SELECT MAX(Дата) AS maxДата
FROM table1
WHERE Дата < (select max(Дата) from table1)
UNION ALL
SELECT MAX(Дата) AS maxДата
FROM table1
WHERE Дата < (select max(Дата) from table1
WHERE Дата < (select max(Дата) from table1))
отбор 3-х макс Дат для каждого Товара для вывода их всех
Скрытый текст
Код
SELECT Товар, MAX(Дата) AS maxДата FROM table1 GROUP BY Товар
UNION ALL
SELECT Товар, MAX(Дата) AS maxДата
FROM table1
WHERE Дата < (select max(Дата) from table1)
GROUP BY Товар
UNION ALL
SELECT Товар, MAX(Дата) AS maxДата
FROM table1
WHERE Дата < (select max(Дата) from table1
WHERE Дата < (select max(Дата) from table1))
GROUP BY Товар
ORDER BY Товар, maxДата DESC
добавив стоимость в запрос - на выходе будет 3 столбца: дата, товар, стоимость...
подсчёт Среднего по 3-м последним датам закупки для каждого Товара
Скрытый текст
Код
SELECT t4.Товар, avg(t4.Стоимость) as [Ср за 3 последние] FROM (
SELECT t1.Товар, t1.Дата ,avg(t1.`Цена за ед без НДС`) as Стоимость FROM table1 t1
INNER JOIN (SELECT Товар, MAX(Дата) AS maxДата FROM table1 GROUP BY Товар) t2
ON (t2.Товар = t1.Товар and t2.maxДата = t1.Дата)
GROUP BY t1.Товар, t1.Дата
UNION ALL
SELECT t1.Товар, t1.Дата ,avg(t1.`Цена за ед без НДС`) as Стоимость FROM table1 t1
INNER JOIN (SELECT Товар, MAX(Дата) AS maxДата
FROM table1
WHERE Дата < (select max(Дата) from table1)
GROUP BY Товар) t2
ON (t2.Товар = t1.Товар and t2.maxДата = t1.Дата)
GROUP BY t1.Товар, t1.Дата
UNION ALL
SELECT t1.Товар, t1.Дата ,avg(t1.`Цена за ед без НДС`) as Стоимость FROM table1 t1
INNER JOIN (SELECT Товар, MAX(Дата) AS maxДата
FROM table1
WHERE Дата < (select max(Дата) from table1
WHERE Дата < (select max(Дата) from table1))
GROUP BY Товар) t2
ON (t2.Товар = t1.Товар and t2.maxДата = t1.Дата)
GROUP BY t1.Товар, t1.Дата) t4
GROUP BY t4.Товар
- (есть рабочий файл с 3-м запросом - [его и в пост№34 можно вставить - у меня получился вес >100кб - пока не могу загрузить], но дошла до него очень окольными путями... - может быть есть прямой путь - проблема в том, что при корректировке запроса до желаемого происходит, насколько понимаю, неявное преобразование типа данных поля Стоимость - возможно, потому что "умная таблица" сама по себе помнит что-то... как это побороть в повседневной жизни (чтобы долго не искать выход)?.. есть ли какая-нибудь рабочая "фишка" побороть эту досадную неприятность?.. пробовала использовать операторы CAST и CONVERT - выдавал ошибку...
p/s/ для ТС - таблица начальная задана именованным диапазоном table1; если не хотите привязываться к имени диапазона в исходных данных - указывать в запросе лист и можно ещё и диапазон столбцов от A: до D (убрать _) [Закупка$A:_D] вместо table1
чтобы не гадать на кофейной гуще, кто вам отвечает и после этого не совершать кучу ошибок - обратитесь к собеседнику на ВЫ - ответ на ваш вопрос получите - а остальное вас не касается (п.п.п. на форумах)
сократила размер файла - вот так он выглядит (xl2010) c 3-им запросом - см вложение ... но на вопросы предыдущего поста ответы ещё очень волнуют - это неявное преобразование типа данных иногда жизни не даёт... какие способы его обходить?.. p.s. файл, как и в случае TheBest - располагать в папке с:\1\
чтобы не гадать на кофейной гуще, кто вам отвечает и после этого не совершать кучу ошибок - обратитесь к собеседнику на ВЫ - ответ на ваш вопрос получите - а остальное вас не касается (п.п.п. на форумах)
1-й вариант не всегда подходит ввиду нач структуры данных, 2-й вариант не срабатывает (проблемный файл не выкладываю - он стал большим в ходе экспериментов по данной теме)
Код
avg(CDbl(t4.Стоимость)) as [Ср за 3 последние]
и
avg(CInt(t4.Стоимость)) as [Ср за 3 последние]
чтобы не гадать на кофейной гуще, кто вам отвечает и после этого не совершать кучу ошибок - обратитесь к собеседнику на ВЫ - ответ на ваш вопрос получите - а остальное вас не касается (п.п.п. на форумах)
тоже не работает... приходится потом руками менять формат ячеек самой "умной" таблицы с даты на общий... а если при обновлении количество строк увеличивается - снова вылазят атавизмы Даты... странно, что CONVERT и CAST не работают - наверно, они только на sql server'e работают
чтобы не гадать на кофейной гуще, кто вам отвечает и после этого не совершать кучу ошибок - обратитесь к собеседнику на ВЫ - ответ на ваш вопрос получите - а остальное вас не касается (п.п.п. на форумах)
TheBestOfTheBest написал: Непонятно, пишите CDbl, а хотите дату.
Дату не хочу, но она вылазит - надо принудительно в CDbl или float (видимо, на языке sql)
чтобы не гадать на кофейной гуще, кто вам отвечает и после этого не совершать кучу ошибок - обратитесь к собеседнику на ВЫ - ответ на ваш вопрос получите - а остальное вас не касается (п.п.п. на форумах)
TheBestOfTheBest написал: Проще умножить на 1 и в выходной таблице поставить формат столбца соответствующий.... это формат ячеек слетает.
1-е не помогло... насчёт 2-го: думаю, формат Даты как-то изначально застрял в "кэше" умной таблицы (для конкретного столбца), и потом при смене запроса в эту же умную таблицу - он воспроизводится, как изначально застрял... наверно, было бы интересно понять, как его чистить? но к сожалению, не знаю... p.s. гипотез много - (может, потому что агрегатная функция max изначально шла для столбца Дат, потом и на avg как-то автоматом пошла... может группировка как-то подвела) - рабочих версий пока нет
чтобы не гадать на кофейной гуще, кто вам отвечает и после этого не совершать кучу ошибок - обратитесь к собеседнику на ВЫ - ответ на ваш вопрос получите - а остальное вас не касается (п.п.п. на форумах)
Smiley могу лишь запрос пополнее предложить - (данные в файле чуть изменены для достижения универсальности, запрос немного исправлен - см Лист1) - вроде бы работает верно и универсально для данной задачи окончательный вариант
Скрытый текст
Код
SELECT t4.Товар, avg(t4.Стоимость) as [Ср за 3 последние] FROM (
SELECT t1.Товар, t1.Дата ,avg(t1.`Цена за ед без НДС`) as Стоимость FROM table1 t1
INNER JOIN (SELECT Товар, MAX(Дата) AS maxДата FROM table1 GROUP BY Товар) t2
ON (t2.Товар = t1.Товар and t2.maxДата = t1.Дата)
GROUP BY t1.Товар, t1.Дата
UNION ALL
SELECT t1.Товар, t1.Дата ,avg(t1.`Цена за ед без НДС`) as Стоимость FROM table1 t1
INNER JOIN (SELECT t0.Товар, MAX(t0.Дата) AS maxДата
FROM table1 t0
WHERE t0.Дата < (select max(Дата) from table1 where t0.Товар= Товар)
GROUP BY t0.Товар) t2
ON (t2.Товар = t1.Товар and t2.maxДата = t1.Дата)
GROUP BY t1.Товар, t1.Дата
UNION ALL
SELECT t1.Товар, t1.Дата ,avg(t1.`Цена за ед без НДС`) as Стоимость FROM table1 t1
INNER JOIN (SELECT t0.Товар, MAX(t0.Дата) AS maxДата
FROM table1 t0
WHERE t0.Дата < (select max(Дата) from table1 where t0.Товар= Товар
And Дата < (select max(Дата) from table1 where t0.Товар= Товар))
GROUP BY t0.Товар) t2
ON (t2.Товар = t1.Товар and t2.maxДата = t1.Дата)
GROUP BY t1.Товар, t1.Дата
) t4
GROUP BY t4.Товар
чтобы не гадать на кофейной гуще, кто вам отвечает и после этого не совершать кучу ошибок - обратитесь к собеседнику на ВЫ - ответ на ваш вопрос получите - а остальное вас не касается (п.п.п. на форумах)
JeyCi написал: думаю, формат Даты как-то изначально застрял в "кэше" умной таблицы (для конкретного столбца), и потом при смене запроса в эту же умную таблицу - он воспроизводится
Если в ходе экспериментов с подключением у кого-нибудь возникнет такая же проблема... Проверить уже не на чем - НО решение данной проблемы видится в этом:
Скрытый текст
по линку на справку: Данные можно отформатировать, и это форматирование сохраняется при обновлении внешних данных. Чтобы форматирование и формулы распространялись на новые строки диапазона, они должны быть отображены по крайней мере в трех из пяти предшествующих строк. Можно включить (или отключить) этот параметр в любое время описанным ниже образом.
Параметры Excel -- Дополнительно. -- Правка -- флажок Расширять форматы и формулы в диапазонах данных
Чтобы отключить автоматическое форматирование диапазона данных, снимите этот флажок.
чтобы не гадать на кофейной гуще, кто вам отвечает и после этого не совершать кучу ошибок - обратитесь к собеседнику на ВЫ - ответ на ваш вопрос получите - а остальное вас не касается (п.п.п. на форумах)
Sub wiggle()
Dim Conn As New ADODB.Connection, this_wb As Workbook, LR&, RR As Range
Set this_wb = ThisWorkbook
Conn.Open "Provider=Microsoft.Jet.OLEDB.4.0; Extended Properties=""Excel 8.0; HDR=Yes;""; Data Source=" & this_wb.FullName
With Sheets("Лист1")
LR = .Cells(Rows.Count, "A").End(xlUp).Row
For Each RR In .Range("A2:A" & CStr(LR) & "")
'~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
.Range(.Cells(RR.Row, 2), .Cells(LR, 2)).CopyFromRecordset _
Conn.Execute("SELECT AVG([Цена за ед без НДС]) " _
& "FROM (SELECT TOP 3 Дата, [Цена за ед без НДС]" _
& "FROM [Закупка$] WHERE Товар = '" & Cells(RR.Row, 1) & "' ORDER BY Дата DESC)")
'~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Next RR
End With
Conn.Close
End Sub
ЗЫ: Сейчас подумаю, как сделать вообще без перебора ячеек.
JeyCi написал: отключить автоматическое форматирование диапазона данных
оказался и вариант попроще (без настроек всего xl) - лишь снять птицу в свойствах таблицы результата-запроса... - если менять запрос уже существующий - чтобы без прошлого форматирования... (много приятных нюансов - в т.ч. и выбранная в запросе последовательность столбцов - а не автоприклеивание новых столбцов при изменении запроса в ту же таблицу)
p.s. потом птицу можно вернуть(если она нужна) - после однократного обновления с новым запросом p.p.s. Smiley - спасибо за ADO... предлагала задачу ТС "рассмотреть руками"... ADODB.Connection - хорошее дополнение про запас
чтобы не гадать на кофейной гуще, кто вам отвечает и после этого не совершать кучу ошибок - обратитесь к собеседнику на ВЫ - ответ на ваш вопрос получите - а остальное вас не касается (п.п.п. на форумах)
Smiley написал: Сейчас подумаю, как сделать вообще без перебора ячеек.
свершилось чудо! - я поняла свои проблемы того дня - почему у меня не работал запрос под спойлером, когда пыталась его адаптировать под эту задачу
Скрытый текст
например, два самых крупных заказа для каждого клиента
Код
WITH Ranked as
(
SELECT *,
Row_Number() OVER (PARTITION BY ID_Customer
ORDER BY amount DESC) [rank]
FROM sample
)
SELECT * FROM Ranked
WHERE [rank] < 3
Данный кусочек посвящен новой функциональности называемой «оконные функции» (Window Functions), также известной широкой общественности под именем «аналитических», или OLAP-функций. К тому же, строго говоря, аналитические функции не совсем правильно относить к OLAP, они не предназначены для многомерного анализа данных, работы с гиперкубами и сложными иерархиями, эти функции осуществляют лишь статистический анализ данных в готовой выборке...
потому что ещё не знала особенностей использования Агрегатных функций... (спасибо Андрей VG) такое (под спойлером), видимо, могло бы работать на SQL Server, а мы ещё в Excel, похоже... вобщем, адаптировался вариант sql'я в «старом стиле»
Код
SELECT s1.Товар, avg(s1.`Цена за ед без НДС`) AS av
FROM table1 s1
WHERE s1.[Дата] IN
(SELECT top 3 s2.[Дата]
FROM table1 s2
WHERE s1.[Товар] = s2.[Товар]
ORDER BY s2.[Дата] DESC)
GROUP BY s1.Товар
p.s. жаль, что ещё не сама написала, но делюсь новым пониманием... что искали в #31(см. цитата), то нашлось пример немного видоизменён для отображения универсальности... пока что так... тоже в папку c:\1\
чтобы не гадать на кофейной гуще, кто вам отвечает и после этого не совершать кучу ошибок - обратитесь к собеседнику на ВЫ - ответ на ваш вопрос получите - а остальное вас не касается (п.п.п. на форумах)