|
|
(161 intermediate revisions by 2 users not shown) |
Line 2: |
Line 2: |
| [[VbzCart]]: [[VbzCart data views|data views]] | | [[VbzCart]]: [[VbzCart data views|data views]] |
| ==Overview== | | ==Overview== |
− | "Views" in [[MySQL]] are like SELECT "queries" in [[MS Access]], i.e. they pull data from existing tables and are themselves usable as data sources in much the same way that tables are (and in which result sets from functions are not).
| + | What [[MS Access]] calls "queries" are called "views" in [[MySQL]], i.e. they pull data from existing tables and are themselves usable as data sources in much the same way that tables are (and in which result sets from functions are not). |
− | ==Views==
| |
− | "Views" in [[MySQL]] are essentially identical to stored queries in [[MS Access]].
| |
| | | |
| Some common prefixes: | | Some common prefixes: |
| * '''qryCbx_''': queries used for filling comboboxes. The unique ID will always be the first field, and the text to display will always be the second field; additional fields may be provided for use in further '''qryCbx_''' queries which show a subset of the results. | | * '''qryCbx_''': queries used for filling comboboxes. The unique ID will always be the first field, and the text to display will always be the second field; additional fields may be provided for use in further '''qryCbx_''' queries which show a subset of the results. |
| * '''qryCat_''': queries which build catalog numbers or information by joining multiple tables. (In Access, the convention was '''qryCatNum_'''.) | | * '''qryCat_''': queries which build catalog numbers or information by joining multiple tables. (In Access, the convention was '''qryCatNum_'''.) |
| + | ==by category== |
| + | ===Inactive=== |
| + | * [[/deprecated]]: queries we're trying to [[/discarded|get rid of]], once we're sure nothing uses them |
| + | * [[/discarded]]: queries apparently no longer in use |
| + | |
| ===Catalog=== | | ===Catalog=== |
− | ====qryCat_Depts====
| + | * [[/qryCat_Depts]] |
− | <section begin=sql /><mysql>CREATE OR REPLACE VIEW qryCat_Depts AS
| + | * '''Title'''-centric: |
− | SELECT
| + | ** [[/qryTitles_Item_info]] |
− | d.ID,
| + | ** [[/qryTitles_ItTyps_grpItems]] |
− | d.Name,
| + | ** [[/qryTitles_ItTyps_ItTyps]] |
− | d.Sort,
| + | ** [[/qryTitles_ItTyps_Titles]] |
− | d.CatKey,
| + | ** [[/qryTitles_Imageless]] - titles with no active images |
− | d.ID_Supplier,
| + | ** [[/qryCat_Titles]] |
− | CONCAT_WS('-',s.CatKey,d.CatKey) AS CatNum
| + | ** [[/qryCat_Titles_Item_stats]] -- item/stock statistics |
− | FROM cat_depts AS d LEFT JOIN cat_supp AS s ON d.ID_Supplier=s.ID;</mysql>
| + | ** [[/qryCat_Titles_Item_count]] -- simpler query for maintenance |
− | <section end=sql />
| + | ** [[/qryCat_Titles_web]] |
− | These will later reference cat_titles instead of titles, when that table is fully migrated.
| + | ** [[/qryCbx_Titles]] |
− | | + | * '''Item'''-centric: |
− | ====v_titles====
| + | ** [[/qryCat_Items_Stock]]: cat_items with stock info |
− | This version still depends on cached _depts table; eliminate this later.
| + | * '''ItTyp'''-centric: |
− | <section begin=sql /><mysql>CREATE OR REPLACE VIEW v_titles AS
| + | ** [[/qryItTypsDepts_grpItems]] |
− | SELECT
| + | ** [[/qryItTypsDepts_ItTyps]] |
− | ID_Title,
| + | * '''Image'''-centric: |
− | SUM(IF(i.isForSale,1,0)) AS cntForSale,
| + | ** [[/qryImgs_byTitle]]: Image info by Title |
− | SUM(IF(i.isInPrint,1,0)) AS cntInPrint,
| + | * [[/qryCat_pages]]: maps http path info to catalog entities |
− | SUM(i.qtyInStock) AS qtyInStock,
| + | ====Catalog Items==== |
− | MIN(i.PriceSell) AS currMinSell,
| + | * [[/qryCbx_Items_data]] |
− | MAX(i.PriceSell) AS currMaxSell,
| + | ** [[/qryCbx_Items]] |
− | d.ID_Supp,
| + | ** [[/qryCbx_Items_active]] |
− | UPPER(CONCAT_WS("-",d.CatNum,t.CatKey)) AS CatNum,
| + | ** [[/qryCbx_Items_for_sale]] |
− | LOWER(CONCAT_WS("/",d.CatWeb_Title,t.CatKey)) AS CatWeb,
| + | ** [[/qryCbx_Items_opt]]: abbreviated version for contexts where Title is already known |
− | t.Name
| + | * [[/qryItems_prices]]: what uses this? |
− | FROM (cat_items AS i LEFT JOIN cat_titles AS t ON i.ID_Title=t.ID) LEFT JOIN _depts AS d ON t.ID_dept=d.ID
| + | ====Catalog Sources==== |
− | GROUP BY i.ID_Title;</mysql>
| + | * [[/qryCtg_Sources_active]] |
− | <section end=sql />
| + | * [[/qryCtg_Items_updates]] |
− | | + | * [[/qryCtg_Items_updates_joinable]] |
− | Old version which depends on 2 cached tables (trying to minimize usage of these):
| + | * [[/qryCtg_Items_active]] |
− | <mysql>CREATE OR REPLACE VIEW v_titles AS
| + | * <s>[[/qryCtg_build_sub]]</s> |
− | SELECT
| + | * <s>[[/qryCtg_build]]</s> |
− | t.*,
| + | * '''[[VbzCart catalog building|building]] process''': |
− | tx.ID_Supp,
| + | ** [[/qryCtg_Items_forUpdJoin]] |
− | tx.CatNum,
| + | ** [[/qryCtg_Upd_join]] |
− | tx.CatWeb,
| + | ** [[/qryCtg_src_dups]] |
− | tx.cntForSale,
| + | ** [[/qryCtgCk_dup_keys]] |
− | tx.cntInPrint,
| |
− | tx.qtyInStock
| |
− | FROM titles AS t LEFT JOIN _titles AS tx on t.ID=tx.ID;</mysql>
| |
− | ====qryCat_Titles====
| |
− | <section begin=sql /><mysql>CREATE OR REPLACE VIEW qryCat_Titles AS
| |
− | SELECT
| |
− | t.ID,
| |
− | t.Name,
| |
− | CONCAT_WS('-',d.CatNum,t.CatKey) AS CatNum,
| |
− | t.CatKey AS CatKey_Title,
| |
− | d.ID_Supplier,
| |
− | t.ID_Dept,
| |
− | t.DateAdded,
| |
− | t.RstkMin AS QtyMin_Rstk,
| |
− | t.Notes,
| |
− | t.Supplier_CatNum AS Supp_CatNum
| |
− | FROM cat_titles AS t LEFT JOIN qryCat_Depts AS d ON t.ID_Dept=d.ID;</mysql>
| |
− | <section end=sql />
| |
− | | |
− | * '''CatKey_Title''' is used in the catalog-building process (Enter Title Groups) when searching within a supplier for a particular title | |
− | | |
− | ===Catalog Items===
| |
− | ====v_items====
| |
− | <section begin=sql /><mysql>CREATE OR REPLACE VIEW `v_items` AS
| |
− | SELECT
| |
− | i.ID,
| |
− | i.CatNum,
| |
− | i.isForSale,
| |
− | i.isMaster,
| |
− | i.qtyInStock,
| |
− | i.isInPrint,
| |
− | i.isCloseOut,
| |
− | i.isPulled,
| |
− | i.isDumped,
| |
− | i.ID_Title,
| |
− | i.ID_ItTyp,
| |
− | i.ID_ItOpt,
| |
− | i.ItOpt_Descr,
| |
− | i.ID_ShipCost,
| |
− | i.PriceBuy,
| |
− | i.PriceSell,
| |
− | i.PriceList,
| |
− | i.Supp_CatNum,
| |
− | io.Sort AS OptSort
| |
− | FROM (
| |
− | `cat_items` AS `i` LEFT JOIN
| |
− | `cat_ioptns` AS `io` ON
| |
− | ((`i`.`ID_ItOpt` = `io`.`ID`)));</mysql>
| |
− | <section end=sql />
| |
− | Used by '''clsItemsExt'''
| |
− | | |
− | ====qryCat_Items====
| |
− | <section begin=sql /><mysql>CREATE OR REPLACE VIEW qryCat_Items AS SELECT
| |
− | i.ID,
| |
− | i.ID_Title,
| |
− | (t.ID IS NOT NULL) AS TitleExists,
| |
− | t.ID_Supplier,
| |
− | i.PriceSell,
| |
− | i.PriceList,
| |
− | i.PriceBuy,
| |
− | i.CatNum,
| |
− | t.CatNum AS Title_CatNum,
| |
− | t.Name AS Title_Name,
| |
− | i.ID_ItTyp,
| |
− | i.ID_ItOpt,
| |
− | i.ItOpt_Descr,
| |
− | i.ItOpt_Sort,
| |
− | CONCAT(t.Name, IF
| |
− | (i.ItOpt_Descr IS NULL,'',CONCAT(
| |
− | ' (',i.ItOpt_Descr,')'
| |
− | )
| |
− | )
| |
− | ) AS Descr,
| |
− | i.Supp_CatNum,
| |
− | i.isForSale,
| |
− | i.isPulled,
| |
− | i.QtyMin_Stk,
| |
− | t.QtyMin_Rstk AS QtyMin_Rstk_Title
| |
− | FROM cat_items AS i LEFT JOIN qryCat_Titles AS t on i.ID_Title=t.ID
| |
− | ORDER BY t.ID IS NOT NULL, i.CatNum, i.ItOpt_Sort;</mysql>
| |
− | <section end=sql />
| |
− | | |
− | * '''MySQL note''': Functions (or CONCAT, anyway) apparently do not like being separated from their opening parenthesis; it seems to resolve the function name as a field name, and (generally) will report that there is no such field.
| |
− | ====qryCbx_Items==== | |
− | <section begin=sql /><mysql>CREATE OR REPLACE VIEW qryCbx_Items_data AS
| |
− | SELECT
| |
− | i.ID,
| |
− | CAST(
| |
− | CONCAT(
| |
− | if(i.isPulled,
| |
− | '*P* ',
| |
− | ''
| |
− | ),
| |
− | if(i.CatNum IS NULL,
| |
− | CONCAT('#',i.ID,' (no cat#)')
| |
− | ,i.CatNum),
| |
− | if(i.Supp_CatNum IS NULL,
| |
− | '',
| |
− | CONCAT(' [',i.Supp_CatNum,']')
| |
− | ),
| |
− | if(i.isForSale,'',' *n/a*'),
| |
− | ' ',
| |
− | if(i.Descr IS NULL,'no description',i.Descr)
| |
− | ) AS CHAR
| |
− | ) AS Descr,
| |
− | i.isPulled,
| |
− | i.isForSale,
| |
− | i.ID_Title,
| |
− | i.CatNum,
| |
− | i.Supp_CatNum,
| |
− | i.PriceSell,
| |
− | i.QtyMin_Stk
| |
− | FROM qryCat_Items AS i
| |
− | ORDER BY NOT i.isPulled, i.isForSale, i.CatNum;
| |
− | | |
− | CREATE OR REPLACE VIEW qryCbx_Items AS
| |
− | SELECT ID, Descr
| |
− | FROM qryCbx_Items_data;
| |
− | | |
− | CREATE OR REPLACE VIEW qryCbx_Items_active AS
| |
− | SELECT ID, Descr
| |
− | FROM qryCbx_Items_data
| |
− | WHERE (NOT isPulled) AND (CatNum IS NOT NULL)
| |
− | ORDER BY CatNum;
| |
− | | |
− | CREATE OR REPLACE VIEW qryCbx_Items_for_sale AS
| |
− | SELECT ID, Descr
| |
− | FROM qryCbx_Items_data
| |
− | WHERE isForSale
| |
− | ORDER BY CatNum;</mysql>
| |
− | <section end=sql />
| |
− | | |
− | * Future refinement: no need to display CatNum, Supp_CatNum, i.Descr if i.isPulled | |
− | * Added more fields for forms which want to display Descr from this query but also need those fields (e.g. Restock Items form): | |
− | ** '''ID_Title''', '''CatNum''', '''PriceSell''', '''QtyMin_Stk'''
| |
− | * Added '''isPulled''' so qryCbx_Items_active can display only non-pulled items (less bandwidth = faster loading)
| |
− | | |
− | An abbreviated version for contexts where the Title is already known
| |
− | <section begin=sql /><mysql>CREATE OR REPLACE VIEW qryCbx_Items_opt AS
| |
− | SELECT
| |
− | i.ID,
| |
− | CAST(
| |
− | CONCAT(
| |
− | if(i.isPulled,
| |
− | '*P* ',
| |
− | ''
| |
− | ),
| |
− | if(i.ID_ItOpt IS NULL,
| |
− | CONCAT('#',i.ID,' (no opt)')
| |
− | ,io.CatKey),
| |
− | if(i.isForSale,'',' *n/a*')
| |
− | ) AS CHAR
| |
− | ) AS Descr,
| |
− | | |
− | i.CatNum
| |
− | FROM cat_items AS i LEFT JOIN cat_ioptns AS io ON i.ID_ItOpt=io.ID;</mysql>
| |
− | <section end=sql />
| |
− | | |
− | ====qryItems_prices====
| |
− | This will eventually contain shipping prices as well, but the shipping costs table hasn't been migrated yet. It also needs to build a description from it.NameSng and i.ItOpt_Descr -- or perhaps there is a better way to do it (haven't we solved this problem elsewhere in a view?)
| |
− | <section begin=sql /><mysql>CREATE OR REPLACE VIEW qryItems_prices AS
| |
− | SELECT
| |
− | i.ID,
| |
− | i.CatNum,
| |
− | i.ID_Title,
| |
− | i.ID_ItTyp,
| |
− | i.ID_ShipCost,
| |
− | i.PriceSell,
| |
− | i.PriceList,
| |
− | i.ItOpt_Descr,
| |
− | i.isInPrint,
| |
− | it.NameSng,
| |
− | it.NamePlr,
| |
− | it.Descr as ItTyp_Descr
| |
− | FROM (cat_items AS i LEFT JOIN cat_ittyps AS it ON i.ID_ItTyp=it.ID)
| |
− | WHERE i.isForSale AND (NULLIF(i.isPulled,0) IS NULL) AND (i.ID_ShipCost IS NOT NULL) AND (i.PriceSell IS NOT NULL)
| |
− | ORDER BY i.CatNum;</mysql>
| |
− | <section end=sql />
| |
− | ===Catalog Sources=== | |
− | ====qryCtg_Sources_active====
| |
− | <section begin=sql /><mysql>CREATE OR REPLACE VIEW qryCtg_Sources_active AS
| |
− | SELECT *
| |
− | FROM ctg_sources AS sc
| |
− | WHERE (sc.DateAvail <= NOW()) AND (sc.ID_Supercede IS NULL);</mysql>
| |
− | <section end=sql />
| |
− | ====qryCtg_Items_updates====
| |
− | <section begin=sql /><mysql>CREATE OR REPLACE VIEW qryCtg_Items_updates AS
| |
− | SELECT
| |
− | NULLIF(CONCAT_WS('/',g.Code,gt.GroupCode,o.CatKey),'') AS CatSfx,
| |
− | gt.ID_Title,
| |
− | g.ID AS ID_TGroup,
| |
− | gt.ID AS ID_TGTitle,
| |
− | gi.ID AS ID_TGItem,
| |
− | gi.ID_ItTyp, gi.ID_ItOpt
| |
− | FROM
| |
− | (
| |
− | (
| |
− | (
| |
− | ctg_titles AS gt LEFT JOIN ctg_groups AS g ON g.ID=gt.ID_Group
| |
− | ) LEFT JOIN qryCtg_Sources_active AS c ON gt.ID_Source=c.ID
| |
− | ) LEFT JOIN ctg_items AS gi ON gi.ID_Group=g.ID
| |
− | ) LEFT JOIN cat_ioptns AS o ON gi.ID_ItOpt=o.ID
| |
− | WHERE
| |
− | (c.ID IS NOT NULL)
| |
− | AND g.isActive
| |
− | AND gt.isActive
| |
− | AND ((gt.WhenDiscont IS NULL) OR (gt.WhenDiscont>NOW()))
| |
− | AND gi.isActive;</mysql>
| |
− | <section end=sql />
| |
− | | |
− | ====qryCtg_Items_updates_joinable====
| |
− | <section begin=sql /><mysql>CREATE OR REPLACE VIEW qryCtg_Items_updates_joinable AS | |
− | SELECT
| |
− | CONCAT_WS('-',u.ID_Title,u.CatSfx) AS IDS_Update,
| |
− | CONCAT_WS('-',t.CatNum,u.CatSfx) AS CatNum,
| |
− | u.*
| |
− | FROM qryCtg_Items_updates AS u LEFT JOIN qryCat_Titles AS t ON u.ID_Title=t.ID;</mysql>
| |
− | <section end=sql />
| |
− | | |
− | ===Orders===
| |
− | ====qryCbx_Orders====
| |
− | <section begin=sql /><mysql>CREATE OR REPLACE VIEW qryCbx_Orders AS | |
− | SELECT
| |
− | ID,
| |
− | CONCAT_WS(' due ',CAST(Number AS CHAR),DATE_FORMAT(WhenNeeded,'%Y-%m-%d')) AS Descr,
| |
− | ID_Pull,
| |
− | WhenNeeded
| |
− | FROM core_orders
| |
− | ORDER BY CONCAT(IFNULL(SortPfx,''),Number) DESC;</mysql>
| |
− | <section end=sql />
| |
− | | |
− | * '''ID_Pull''' and '''WhenNeeded''' are needed for [[#qryStock_forOpenOrders]] | |
− | | |
− | ====qryOrderLines_notPkgd====
| |
− | Active order lines which have yet to be (completely) put into a package
| |
− | <section begin=sql /><mysql>CREATE OR REPLACE VIEW qryOrderLines_notPkgd AS
| |
− | SELECT
| |
− | oi.ID,
| |
− | oi.ID_Order,
| |
− | oi.ID_Item,
| |
− | oi.CatNum,
| |
− | oi.Descr,
| |
− | oi.QtyOrd,
| |
− | oi.Price,
| |
− | oi.QtyOrd
| |
− | -SUM(
| |
− | IFNULL(pi.QtyShipped,0)
| |
− | +IFNULL(pi.QtyNotAvail,0)
| |
− | +IFNULL(pi.QtyKilled,0)
| |
− | ) AS QtyOpen,
| |
− | SUM(IFNULL(pi.QtyShipped,0)) AS QtyShipped,
| |
− | SUM(IFNULL(pi.QtyShipped,0)
| |
− | +IFNULL(pi.QtyNotAvail,0)
| |
− | +IFNULL(pi.QtyKilled,0)) AS QtyHandled
| |
− | FROM
| |
− | ord_lines AS oi
| |
− | LEFT JOIN ord_pkg_lines pi ON pi.ID_OrdLine=oi.ID
| |
− | GROUP BY
| |
− | oi.ID,
| |
− | oi.ID_Order,
| |
− | oi.ID_Item,
| |
− | oi.CatNum,
| |
− | oi.Descr,
| |
− | oi.QtyOrd,
| |
− | oi.Price
| |
− | HAVING oi.QtyOrd-QtyHandled >0;</mysql>
| |
− | <section end=sql />
| |
− | ====qryOrders_Active====
| |
− | Show all orders which are currently active. For now, this just shows orders which haven't been pulled , but later it will look at the order state. As simple as it is, it's still useful to have this as a separate query because:
| |
− | * Removing unneeded records before sending data helps to reduce bandwidth a little bit when called from a remote process | |
− | * Serves as a reference which can be used unaltered even after the method of determining whether an order is "active" changes | |
− | <section begin=sql /><mysql>CREATE OR REPLACE VIEW qryOrders_Active AS
| |
− | SELECT * FROM core_orders WHERE ID_Pull IS NULL;</mysql>
| |
− | <section end=sql />
| |
− | | |
− | ===Packages===
| |
− | ====qryPkgLines_byOrdLine_andItem====
| |
− | <section begin=sql /><mysql>CREATE OR REPLACE VIEW qryPkgLines_byOrdLine_andItem AS
| |
− | SELECT
| |
− | ID_OrdLine,
| |
− | ID_Item,
| |
− | Sum(
| |
− | IFNULL(pl.QtyShipped,0)+
| |
− | IFNULL(pl.QtyNotAvail,0)+
| |
− | IFNULL(pl.QtyKilled,0)
| |
− | ) AS QtyDone,
| |
− | Sum(pl.QtyShipped) AS QtyShipped,
| |
− | Sum(pl.QtyNotAvail) AS QtyNotAvail,
| |
− | Sum(pl.QtyKilled) AS QtyKilled,
| |
− | Sum(pl.QtyExtra) AS QtyExtra
| |
− | FROM ord_pkg_lines AS pl
| |
− | GROUP BY ID_OrdLine, ID_Item;</mysql>
| |
− | <section end=sql />
| |
− | ====qryOrdLines_PkgdQtys====
| |
− | '''Depends on''': qryPkgLines_byOrdLine_andItem
| |
− | <section begin=sql /><mysql>CREATE OR REPLACE VIEW qryOrdLines_PkgdQtys AS
| |
− | SELECT
| |
− | ol.ID,
| |
− | ol.ID_Order,
| |
− | ol.ID_Item,
| |
− | ol.QtyOrd,
| |
− | pl.QtyDone,
| |
− | pl.QtyShipped,
| |
− | pl.QtyExtra,
| |
− | pl.QtyNotAvail,
| |
− | pl.QtyKilled
| |
− | FROM ord_lines AS ol
| |
− | LEFT JOIN qryPkgLines_byOrdLine_andItem AS pl ON pl.ID_OrdLine=ol.ID;</mysql>
| |
− | <section end=sql />
| |
− | ====qryOrdLines_open====
| |
− | '''Depends on''': qryOrdLines_PkgdQtys
| |
− | <section begin=sql /><mysql>CREATE OR REPLACE VIEW qryOrdLines_open AS
| |
− | SELECT
| |
− | ol.ID,
| |
− | o.ID AS ID_Order,
| |
− | ol.ID_Item,
| |
− | Sum(ol.QtyOrd) AS QtyOrd,
| |
− | Sum(ol.QtyDone) AS QtyDone,
| |
− | Min(WhenOpened) AS WhenOldestOrder,
| |
− | Min(WhenNeeded) AS WhenSoonestDue
| |
− | FROM qryOrders_Active AS o LEFT JOIN qryOrdLines_PkgdQtys AS ol ON ol.ID_Order=o.ID
| |
− | WHERE IFNULL(ol.QtyOrd,0)-IFNULL(ol.QtyDone,0)<>0
| |
− | GROUP BY ol.ID, o.ID, ol.ID_Item;</mysql>
| |
− | <section end=sql />
| |
− | | |
− | ===Restocks===
| |
− | ====qryCbx_Restocks====
| |
− | I don't know [[WTF]] is going on here. MySQL wouldn't let me create this as one big query (no error message, just "query cancelled"), so I tried to split it into two parts and union them -- but I get the same error message. For now, I'm just defining the subqueries in MySQL and the UNION in Access. :-P
| |
− | <section begin=sql /><mysql>CREATE OR REPLACE VIEW qryCbx_Restocks_byStatus AS
| |
− | SELECT
| |
− | r.ID,
| |
− | CAST(
| |
− | CONCAT(
| |
− | CAST(COALESCE(
| |
− | CONCAT('X ',DATE_FORMAT(r.WhenKilled,'%Y-%m-%d')),
| |
− | CONCAT('R ',DATE_FORMAT(r.WhenReceived,'%Y-%m-%d')),
| |
− | CONCAT('O ',DATE_FORMAT(r.WhenOrdered,'%Y-%m-%d')),
| |
− | CONCAT('D ',DATE_FORMAT(r.WhenDebited,'%Y-%m-%d')),
| |
− | CONCAT('C ',DATE_FORMAT(r.WhenCreated,'%Y-%m-%d'))
| |
− | ) AS BINARY),
| |
− | ' ',
| |
− | s.CatKey,
| |
− | IFNULL(CONCAT(' [',r.PurchOrdNum,']'),'')
| |
− | ) AS CHAR
| |
− | ) AS Descr,
| |
− | NOT IsLocked AS IsOpen,
| |
− | r.WhenOrdered,
| |
− | r.WhenReceived,
| |
− | r.WhenConfirmed,
| |
− | r.ID_Supplier
| |
− | FROM core_restocks AS r LEFT JOIN cat_supp AS s ON r.ID_Supplier=s.ID
| |
− | ORDER BY COALESCE(r.WhenKilled,r.WhenReceived,r.WhenOrdered,r.WhenDebited,r.WhenCreated) DESC;
| |
− | | |
− | CREATE OR REPLACE VIEW qryCbx_Restocks_byPurchOrd AS
| |
− | SELECT
| |
− | r.ID,
| |
− | CAST(r.PurchOrdNum AS CHAR) AS Descr,
| |
− | NOT IsLocked AS IsOpen,
| |
− | r.WhenOrdered,
| |
− | r.WhenReceived,
| |
− | r.WhenConfirmed,
| |
− | r.ID_Supplier
| |
− | FROM core_restocks AS r WHERE r.PurchOrdNum IS NOT NULL
| |
− | ORDER BY COALESCE(r.WhenKilled,r.WhenReceived,r.WhenOrdered,r.WhenDebited,r.WhenCreated) DESC;
| |
− | | |
− | CREATE OR REPLACE VIEW qryCbx_Restocks AS
| |
− | SELECT * FROM qryCbx_Restocks_byStatus
| |
− | UNION
| |
− | SELECT * FROM qryCbx_Restocks_byPurchOrd;</mysql>
| |
− | <section end=sql />
| |
| | | |
− | ====qryFrm_RestockLines==== | + | ====Catalog Topics==== |
− | <section begin=sql /><mysql>CREATE OR REPLACE VIEW qryFrm_RestockLines AS
| + | * '''titles x topics''': |
− | SELECT
| + | ** [[/qryTitleTopic_Titles]]: more title information |
− | ri.ID,
| + | ** [[/qryTitleTopic_Topics]]: more topic information |
− | ri.ID_Restock,
| + | ** [[/qryTitleTopic_Title_avail]]: title availability information |
− | ri.ID_Item,
| + | ===Ordering=== |
− | ci.CatNum,
| + | ====Carts==== |
− | ci.Supp_CatNum,
| + | * [[/qryCarts_info]] |
− | ci.PriceSell,
| + | ** [[/qrySub_Carts_info_data]] |
− | ci.QtyMin_Stk,
| + | ** [[/qrySub_Carts_info_items]] |
− | o.Number AS OrderName,
| + | ====Customers==== |
− | ci.Descr AS ItemDescr,
| + | * [[/qryCustAddrs]] |
− | o.WhenNeeded,
| + | * [[/qryCbx_CustNames]] |
− | If(t.RstkMin = 1, '', t.RstkMin) AS RstkMinStr,
| + | ====Orders==== |
− | ri.QtyOrd,
| + | * [[/qryCbx_Orders]] |
− | ri.QtyNeed,
| + | * [[/qryOrderLines_notPkgd]] |
− | ri.QtyExp,
| + | * [[/qryOrders_Active]] |
− | ri.InvcLineNo,
| + | * [[/qryOrderLines_Active]] |
− | ri.InvcQtyOrd,
| + | * [[/qtyOrderItems_Active]] |
− | ri.InvcQtySent,
| + | * [[/qry_PkgItem_qtys_byOrder]] |
− | ri.isGone,
| + | * [[/qryOrdItms_Pkg_qtys]] |
− | ri.QtyRecd,
| + | * [[/qryOrdItms_open]] |
− | ri.QtyFiled,
| + | * [[/qryItms_open]] |
− | ri.CostExpPer,
| + | * [[/qryItms_to_restock_union]] |
− | ri.CostInvPer,
| + | * [[/qryItms_to_restock]] |
− | ri.CostInvTot,
| + | ====Packages==== |
− | ri.CostActTot,
| + | * [[/qryPkgLines_byOrdLine_andItem]] |
− | ri.CostActBal,
| + | * [[/qryOrdLines_PkgdQtys]] |
− | ri.Notes
| + | * [[/qryOrdLines_open]] |
− | FROM
| + | * [[/qryOrders_Pulled]] |
− | (
| + | * [[/qryPkgs_Pull_status]] |
− | (rstk_lines AS ri
| + | * for reports: |
− | LEFT JOIN core_orders AS o ON ri.ID_Order=o.ID)
| + | ** [[/qryRpt_Pkg_Lines]] |
− | LEFT JOIN qryCbx_Items_data AS ci ON ri.ID_Item=ci.ID)
| + | *** [[/qryPkgLines_qtys_done]] |
− | LEFT JOIN cat_titles AS t ON ci.ID_Title=t.ID;</mysql>
| + | *** <s>[[/qryPkgLines_qtys_done_ord_sum]]</s> - not used |
− | <section end=sql />
| + | ** [[/qryRpt_Pkg_Trx]] |
| | | |
− | * A lot of these fields were added back when this query was still the data source for qryFrm_RestockLines_byItem; this is no longer the case. Probably the only customer for this query is the Restock Items entry form, so any fields not needed there can probably be done away with. | + | ====Restocks==== |
| + | * '''all restock requests''': |
| + | ** [[/qryRstks_info]] |
| + | ** [[/qryRstkReq_Item_Rcd_status]] |
| + | ** [[/qryRstkReq_Item_status]] |
| + | *** [[/qryRstkReq_Item_status_Req_info]] |
| + | *** [[/qryRstkReq_Items_expected]]: show only expected items |
| + | ** [[/qryCbx_RstkReq]] |
| + | *** [[/qryRstkReq_by_status]] |
| + | *** [[/qryRstkReq_by_PurchOrd]] |
| + | * '''filtered by status''': |
| + | ** [[/qryRstks_active]]: not terminated = !(closed, orphaned or killed - see {{l/vc/term|restock/status}}) |
| + | *** [[/qryRstks_unsent]]: created but not ordered yet |
| + | **** [[/qryRstkItms_unsent]] |
| + | ***** [[/qryRstkItms_unsent_for_order]] |
| + | ** [[/qryRstks_inactive]]: all the rest |
| | | |
− | ====qryFrm_RestockLines_byItem==== | + | ====Shipping==== |
− | Basically the same as qryFrm_RestockLines, but grouped by ID_Item and with more Item-related fields
| + | * [[/qryPkgs_status]] |
− | <section begin=sql /><mysql>CREATE OR REPLACE VIEW qryFrm_RestockLines_byItem AS
| |
− | SELECT
| |
− | CONCAT(ri.ID_Item,'-',ri.ID_Restock) AS Key_RstkItem,
| |
− | ri.ID_Item,
| |
− | ri.ID_Restock,
| |
− | i.Descr AS ItemDescr,
| |
− | i.CatNum,
| |
− | i.Supp_CatNum,
| |
− | SUM(IFNULL(ri.QtyOrd,0)) AS QtyOrd,
| |
− | SUM(IFNULL(ri.QtyExp,0)) AS QtyExp,
| |
− | ri.CostExpPer,
| |
− | i.PriceSell,
| |
− | i.QtyMin_Stk
| |
− | FROM rstk_lines AS ri LEFT JOIN qryCbx_Items_data AS i ON ri.ID_Item=i.ID
| |
− | GROUP BY ri.ID_Restock, ri.ID_Item, i.CatNum, i.Supp_CatNum, ri.CostExpPer, i.PriceSell, i.QtyMin_Stk
| |
− | ORDER BY i.CatNum;</mysql>
| |
− | <section end=sql />
| |
− | ====qryRstkLines_en_route====
| |
− | Lines from restocks which exist but have not yet received or cancelled. It's assumed that any restocks just sitting around (not ordered but not cancelled) are being prepared and will be used for an actual order.
| |
− | <section begin=sql /><mysql>CREATE OR REPLACE VIEW qryRstkLines_en_route AS
| |
− | SELECT ri.*
| |
− | FROM rstk_lines AS ri LEFT JOIN core_restocks AS r ON ri.ID_Restock=r.ID
| |
− | WHERE (r.WhenReceived IS NULL) AND (r.WhenKilled IS NULL);</mysql>
| |
− | <section end=sql />
| |
− | ====v_rstk_lines_wItemInfo====
| |
− | <section begin=sql /><mysql>CREATE OR REPLACE VIEW v_rstk_lines_wItemInfo AS
| |
− | SELECT
| |
− | ri.*,
| |
− | i.ID_Title,
| |
− | IFNULL(r.WhenOrdered,r.WhenCreated) AS WhenDone
| |
− | FROM
| |
− | (rstk_lines AS ri
| |
− | LEFT JOIN cat_items AS i ON ri.ID_Item=i.ID)
| |
− | LEFT JOIN core_restocks AS r ON ri.ID_Restock=r.ID;</mysql>
| |
− | <section end=sql />
| |
| | | |
| ===Stock=== | | ===Stock=== |
− | ====v_stk_lines_remaining==== | + | ====new queries==== |
− | View listing stk_items actually in stock, which is actually different things:
| + | * [[/qryStk_Bins_w_info]] |
− | * "forSale": items which are visible as "in stock" to customers
| + | * [[/qryStk_lines_remaining]] |
− | * "forShip": items which are available for shipping
| + | ** [[/qryStk_lines_remaining_byBin]] |
− | * items neither for shipping nor for sale (probably some kind of recordkeeping purpose)
| + | ** [[/qryStk_lines_remaining_forSale]] |
− | <section begin=sql /><mysql>CREATE OR REPLACE VIEW v_stk_lines_remaining AS
| + | *** [[/qryStkItms_for_sale]] |
− | SELECT
| |
− | st.ID,
| |
− | st.ID_Bin,
| |
− | st.ID_Item,
| |
− | IF(sb.isForSale,st.Qty,0) AS QtyForSale,
| |
− | IF(sb.isForShip,st.Qty,0) AS QtyForShip,
| |
− | st.Qty AS QtyExisting,
| |
− | st.CatNum,
| |
− | st.WhenAdded,
| |
− | st.WhenChanged,
| |
− | st.WhenCounted,
| |
− | st.Notes,
| |
− | sb.ID_Place,
| |
− | sp.Name AS WhName
| |
− | FROM
| |
− | (
| |
− | stk_items AS st
| |
− | LEFT JOIN stk_bins AS sb
| |
− | ON sb.ID=st.ID_Bin
| |
− | )
| |
− | LEFT JOIN stk_places AS sp
| |
− | ON sb.ID_Place=sp.ID
| |
− | WHERE (st.WhenRemoved IS NULL) AND (sb.WhenVoided IS NULL) AND (st.Qty <> 0);</mysql>
| |
− | <section end=sql />
| |
− | ====v_stk_items_remaining====
| |
− | <section begin=sql /><mysql>CREATE OR REPLACE VIEW v_stk_items_remaining AS
| |
− | SELECT
| |
− | ID_Item,
| |
− | SUM(QtyForSale) AS QtyForSale,
| |
− | SUM(QtyForShip) AS QtyForShip,
| |
− | SUM(QtyExisting) AS QtyExisting
| |
− | FROM v_stk_lines_remaining
| |
− | GROUP BY ID_Item;</mysql>
| |
− | <section end=sql />
| |
− | ====v_stk_titles_remaining====
| |
− | <section begin=sql /><mysql>CREATE OR REPLACE VIEW v_stk_titles_remaining AS
| |
− | SELECT
| |
− | ID_Title,
| |
− | SUM(QtyForSale) AS QtyForSale,
| |
− | SUM(QtyForShip) AS QtyForShip,
| |
− | SUM(QtyExisting) AS QtyExisting
| |
− | FROM v_stk_lines_remaining AS s LEFT JOIN cat_items AS i ON s.ID_Item=i.ID
| |
− | GROUP BY i.ID_Title;</mysql>
| |
− | <section end=sql />
| |
− | | |
− | ====v_stk_byItemAndBin====
| |
− | <section begin=sql /><mysql>CREATE OR REPLACE VIEW v_stk_byItemAndBin AS
| |
− | SELECT
| |
− | ID_Item,
| |
− | ID_Bin,
| |
− | SUM(QtyForSale) AS QtyForSale,
| |
− | SUM(QtyForShip) AS QtyForShip,
| |
− | SUM(QtyExisting) AS QtyExisting
| |
− | FROM v_stk_lines_remaining
| |
− | GROUP BY ID_Item, ID_Bin
| |
− | HAVING SUM(QtyExisting)>0;</mysql>
| |
− | <section end=sql />
| |
− | ====v_stk_byItemAndBin_wItemInfo====
| |
− | Is anything actually using this? '''Document!''' (I've tentatively removed the link in Access.)
| |
− | <section begin=sql /><mysql>CREATE OR REPLACE VIEW v_stk_byItemAndBin_wItemInfo AS
| |
− | SELECT * FROM v_stk_byItemAndBin AS s LEFT JOIN qryCat_Items AS i ON s.ID_Item=i.ID;</mysql>
| |
− | <section end=sql />
| |
− | | |
− | ====v_stk_byItemAndBin_wInfo====
| |
− | <section begin=sql /><mysql>CREATE OR REPLACE VIEW v_stk_byItemAndBin_wInfo AS
| |
− | SELECT
| |
− | s.*,
| |
− | i.*,
| |
− | b.ID_Place,
| |
− | b.Code AS BinCode,
| |
− | b.Descr AS BinDescr
| |
− | FROM
| |
− | (
| |
− | v_stk_byItemAndBin AS s LEFT JOIN qryCat_Items AS i ON s.ID_Item=i.ID
| |
− | ) LEFT JOIN stk_bins AS b ON s.ID_Bin=b.ID;</mysql>
| |
− | <section end=sql />
| |
− | ====qryStk_lines_remaining_forSale====
| |
− | <section begin=sql /><mysql>CREATE OR REPLACE VIEW qryStk_lines_remaining_forSale AS
| |
− | SELECT *
| |
− | FROM v_stk_lines_remaining
| |
− | WHERE QtyForSale>0;</mysql>
| |
− | <section end=sql />
| |
− | ====qryOrdLines_status_union====
| |
− | * '''Depends on''': qryOrdLines_open, qryRstkLines_en_route, v_stk_lines_remaining
| |
− | This is another one of those union queries that is "cancelled" while you're trying to create it... but in this case, it does get created.
| |
− | <section begin=sql /><mysql>CREATE OR REPLACE VIEW qryOrdLines_status_union AS
| |
− | SELECT
| |
− | /* 1 */ CONCAT("oio-",oio.ID) AS Source,
| |
− | /* 2 */ oio.ID AS ID,
| |
− | /* 3 */ oio.ID_Order,
| |
− | /* 4 */ oio.ID_Item,
| |
− | /* 5 */ oio.QtyOrd,
| |
− | /* 6 */ oio.QtyDone,
| |
− | /* 7 */ 0 AS QtyOnRstk,
| |
− | /* 8 */ 0 AS QtyOnHand,
| |
− | /* 9 */ 0 AS QtyMin,
| |
− | /* 10 */ oio.WhenOldestOrder,
| |
− | /* 11 */ oio.WhenSoonestDue
| |
− | FROM qryOrdLines_open AS oio
| |
− | UNION
| |
− | SELECT
| |
− | /* 1 */ CONCAT("rie-",rie.ID) AS Source,
| |
− | /* 2 */ rie.ID AS ID,
| |
− | /* 3 */ rie.ID_Order,
| |
− | /* 4 */ rie.ID_Item,
| |
− | /* 5 */ 0 AS QtyOrd,
| |
− | /* 6 */ 0 AS QtyDone,
| |
− | /* 7 */ IF(rie.QtyExp > rie.QtyOrd,rie.QtyExp,rie.QtyOrd) AS QtyOnRstk,
| |
− | /* 8 */ 0 AS QtyOnHand,
| |
− | /* 9 */ 0 AS QtyMin,
| |
− | /* 10 */ NULL AS WhenOldestOrder,
| |
− | /* 11 */ NULL AS WhenSoonestDue
| |
− | FROM qryRstkLines_en_route AS rie
| |
− | UNION
| |
− | SELECT
| |
− | /* 1 */ CONCAT("srs-",srs.ID) AS Source,
| |
− | /* 2 */ 0 AS ID,
| |
− | /* 3 */ NULL AS ID_Order,
| |
− | /* 4 */ srs.ID_Item,
| |
− | /* 5 */ 0 AS QtyOrd,
| |
− | /* 6 */ 0 AS QtyDone,
| |
− | /* 7 */ 0 AS QtyOnRstk,
| |
− | /* 8 */ srs.QtyForShip AS QtyOnHand,
| |
− | /* 9 */ 0 AS QtyMin,
| |
− | /* 10 */ NULL AS WhenOldestOrder,
| |
− | /* 11 */ NULL AS WhenSoonestDue
| |
− | FROM v_stk_lines_remaining AS srs
| |
− | UNION
| |
− | SELECT
| |
− | /* 1 */ CONCAT("itm-",itm.ID) AS Source,
| |
− | /* 2 */ NULL AS ID,
| |
− | /* 3 */ NULL AS ID_Order,
| |
− | /* 4 */ itm.ID AS ID_Item,
| |
− | /* 5 */ 0 AS QtyOrd,
| |
− | /* 6 */ 0 AS QtyDone,
| |
− | /* 7 */ 0 AS QtyOnRsk,
| |
− | /* 8 */ 0 AS QtyOnHand,
| |
− | /* 9 */ QtyMin_Stk AS QtyMin,
| |
− | /* 10 */ NULL AS WhenOldestOrder,
| |
− | /* 11 */ NULL AS WhenSoonestDue
| |
− | FROM cat_items AS itm;</mysql>
| |
− | <section end=sql />
| |
| | | |
− | ====qryItems_ord_status====
| + | * [[/qryStk_items_remaining]] |
− | '''Depends on''': qryItems_ord_status_union
| + | * [[/qryStk_byItem_byBin]] |
− | Status with regard to ordering, i.e. quantities on hand, quantities needed, etc. Used by the "items needed (for restocking)" form, via [[#qryItems_to_restock]]. This was originally in a different section, but it has to be created after qryOrdLines_status_union.
| |
− | <section begin=sql /><mysql>CREATE OR REPLACE VIEW qryItems_ord_status AS
| |
− | SELECT
| |
− | i.ID_Item,
| |
− | SUM(i.QtyOrd) AS QtyOrd,
| |
− | SUM(i.QtyDone) AS QtyDone,
| |
− | SUM(i.QtyOnRstk) AS QtyOnRstk,
| |
− | SUM(i.QtyOnHand) AS QtyOnHand,
| |
− | MAX(i.QtyMin) AS QtyMin,
| |
− | SUM(
| |
− | IFNULL(i.QtyOrd,0)-IFNULL(i.QtyOnRstk,0)-IFNULL(i.QtyOnHand,0)
| |
− | )+IFNULL(MAX(i.QtyMin),0) AS QtyToGet,
| |
− | MIN(i.WhenOldestOrder) AS WhenOldestOrder,
| |
− | MIN(i.WhenSoonestDue) AS WhenSoonestDue,
| |
− | COUNT(i.Source) AS RecCount,
| |
− | CAST(GROUP_CONCAT(DISTINCT i.Source SEPARATOR ' ') AS CHAR) AS Sources
| |
− | FROM qryOrdLines_status_union AS i
| |
− | GROUP BY i.ID_Item;</mysql>
| |
− | <section end=sql />
| |
− | ====qryItems_to_restock====
| |
− | '''Depends on''': qryItems_ord_status
| |
− | <section begin=sql /><mysql>CREATE OR REPLACE VIEW qryItems_to_restock AS
| |
− | SELECT
| |
− | qi.*,
| |
− | ci.CatNum,
| |
− | ci.isForSale,
| |
− | ci.ID_Supplier,
| |
− | ci.QtyMin_Stk,
| |
− | ci.QtyMin_Rstk_Title,
| |
− | ci.PriceSell,
| |
− | ci.PriceBuy
| |
− | FROM qryItems_ord_status AS qi LEFT JOIN qryCat_Items AS ci ON ci.ID=qi.ID_Item
| |
− | WHERE QtyToGet>0;</mysql>
| |
− | <section end=sql />
| |
− | ====qryStock_forOpenOrders====
| |
− | Show all stock available to fill open orders, along with helpful information about the Bin, Order, and Item:
| |
− | <section begin=sql /><mysql>CREATE OR REPLACE VIEW qryStock_forOpenOrders AS
| |
− | SELECT
| |
− | s.ID_Bin,
| |
− | s.ID_Item,
| |
− | oi.ID_Order,
| |
− | oi.QtyOpen,
| |
− | s.QtyForSale,
| |
− | s.QtyForShip,
| |
− | o.WhenNeeded,
| |
− | o.Descr AS OrdText,
| |
− | o.ID_Pull,
| |
− | CONCAT_WS(' ',s.CatNum,s.Descr) AS ItemText,
| |
− | /* s.BinCode,
| |
− | s.BinDescr, are these ever needed? */
| |
− | CONCAT_WS(' ',s.BinCode,s.BinDescr) AS BinText
| |
− | FROM (v_stk_byItemAndBin_wInfo AS s LEFT JOIN qryOrderLines_notPkgd AS oi ON s.ID_Item=oi.ID_Item) LEFT JOIN qryCbx_Orders AS o ON oi.ID_Order=o.ID
| |
− | WHERE (NOT s.isPulled) AND (o.ID_Pull IS NULL) AND (QtyOpen) AND (QtyForShip);</mysql>
| |
− | <section end=sql />
| |
| | | |
− | * There's a possibility this query will return wrong information when there are multiple stock lines corresponding to the items needed; further testing would be a good idea. | + | * [[/qryStk_lines_Title_info]] |
| | | |
− | ====qryStock_byOpt_andType==== | + | ====old queries==== |
− | This is used for displaying the "stock" area. The basic records are items, but they're only ones that are in stock, so "Stock" is shorthand for "items that are in stock" in this case. | + | This was the first batch of queries I created, before I had decided to go with the qry prefix as in Access. |
− | <section begin=sql /><mysql>CREATE OR REPLACE VIEW qryStock_byOpt_andType AS
| + | * [[/v_stk_titles_remaining]] |
− | SELECT
| + | * [[/v_stk_byItemAndBin_wItemInfo]] |
− | i.ID_ItTyp,
| |
− | i.ID_ItOpt,
| |
− | SUM(i.qtyInStock) AS qtyInStock,
| |
− | it.NameSng AS It_NameSng,
| |
− | it.NamePlr AS It_NamePlr,
| |
− | io.CatKey AS Io_CatKey,
| |
− | io.Descr AS Io_Descr,
| |
− | IFNULL(it.Sort,'ZZZ') AS It_Sort
| |
− | FROM (cat_items AS i LEFT JOIN cat_ioptns AS io ON i.ID_ItOpt=io.ID)
| |
− | LEFT JOIN cat_ittyps AS it ON i.ID_ItTyp=it.ID
| |
− | GROUP BY i.ID_ItTyp, i.ID_ItOpt, io.Sort
| |
− | HAVING SUM(i.qtyInStock)
| |
− | ORDER BY It_Sort,io.Sort;</mysql>
| |
− | <section end=sql />
| |
− | ====qryStock_Titles_most_recent====
| |
− | This defines what the "latest stock" page shows; as given here, it displays the 100 titles most recently added to stock.
| |
− | <section begin=sql /><mysql>CREATE OR REPLACE VIEW qryStock_Titles_most_recent AS
| |
− | SELECT
| |
− | i.ID_Title,
| |
− | s.QtyForSale AS QtyAdded,
| |
− | MAX(s.WhenAdded) AS WhenAdded,
| |
− | st.QtyForSale AS QtyAvail
| |
− | FROM (v_stk_lines_remaining AS s LEFT JOIN cat_items AS i ON s.ID_Item=i.ID) LEFT JOIN v_stk_titles_remaining AS st ON i.ID_Title=st.ID_Title
| |
− | GROUP BY i.ID_Title
| |
− | HAVING QtyAdded
| |
− | ORDER BY WhenAdded DESC
| |
− | LIMIT 100;</mysql>
| |
− | <section end=sql />
| |
| | | |
| ===Caching=== | | ===Caching=== |
| Caching should only be used for catalog display. | | Caching should only be used for catalog display. |
− | ====v_data_flow====
| + | * [[/qryCache_Flow_Procs]] |
− | <section begin=sql /><mysql> CREATE OR REPLACE VIEW v_data_flow AS
| |
− | SELECT
| |
− | df.ID_Srce,
| |
− | df.ID_Dest,
| |
− | df.ID_Proc,
| |
− | dfx.doesClear
| |
− | FROM data_flow AS df LEFT JOIN data_procs AS dfx ON df.ID_Proc=dfx.ID
| |
− | ORDER BY dfx.doesClear;</mysql>
| |
− | <section end=sql />
| |