Uso de DWS para analizar el estado operativo de una tienda departamental
Antecedentes
En esta práctica, los datos comerciales diarios de cada tienda minorista se cargan desde OBS a la tabla correspondiente en el clúster del almacén de datos para resumir y consultar los KPI. Estos datos incluyen la facturación de las tiendas, el flujo de clientes, el ranking de ventas mensuales, la tasa de conversión mensual del flujo de clientes, la relación precio-alquiler mensual y las ventas por unidad de área. Esta práctica demuestra la consulta y el análisis multidimensional de DWS en escenarios minoristas.
Los datos de ejemplo se han cargado en la carpeta retail-data en un bucket de OBS y todas las cuentas de Huawei Cloud tienen permiso de solo lectura para acceder al bucket de OBS.
Procedimiento general
Esta práctica dura unos 60 minutos. El proceso es el siguiente:
Regiones admitidas
La Tabla 1 describe las regiones donde se han cargado los datos de OBS.
| Región | Bucket de OBS |
|---|---|
| CN North-Beijing1 | dws-demo-cn-north-1 |
| CN North-Beijing2 | dws-demo-cn-north-2 |
| CN North-Beijing4 | dws-demo-cn-north-4 |
| CN North-Ulanqab1 | dws-demo-cn-north-9 |
| CN East-Shanghai1 | dws-demo-cn-east-3 |
| CN East-Shanghai2 | dws-demo-cn-east-2 |
| CN South-Guangzhou | dws-demo-cn-south-1 |
| CN South-Guangzhou-InvitationOnly | dws-demo-cn-south-4 |
| CN-Hong Kong | dws-demo-ap-southeast-1 |
| AP-Singapore | dws-demo-ap-southeast-3 |
| AP-Bangkok | dws-demo-ap-southeast-2 |
| LA-Santiago | dws-demo-la-south-2 |
| AF-Johannesburg | dws-demo-af-south-1 |
| LA-Mexico City1 | dws-demo-na-mexico-1 |
| LA-Mexico City2 | dws-demo-la-north-2 |
| RU-Moscow2 | dws-demo-ru-northwest-2 |
| LA-Sao Paulo1 | dws-demo-sa-brazil-1 |
Preparativos
- Ha registrado una cuenta de DWS y la cuenta no está en mora ni congelada.
- Obtenga la AK/SK de la cuenta consultando Creación de una clave de acceso.
- Cree un clúster consultando Creación de un clúster.
Paso 1: Importación de datos de muestra de la tienda departamental
Después de conectarse al clúster mediante la herramienta cliente SQL, realice las siguientes operaciones en la herramienta cliente SQL para importar los datos de muestra de las tiendas departamentales minoristas y realizar consultas.
- En la puesta en marcha del servicio, se recomienda utilizar el SQL Editor para conectarse al clúster. Para obtener más información, consulte Uso del SQL Editor para conectarse a un clúster.
También puede utilizar otros métodos (como la herramienta de línea de comandos gsql) para conectarse al clúster. Para obtener más información, consulte Conexión a un clúster de DWS.
- Ejecute la siguiente instrucción para crear la base de datos retail:
1CREATE DATABASE retail encoding 'utf8' template template0;
- Cambie a la base de datos retail recién creada y cree tablas de base de datos.
Los datos de muestra consisten en 10 tablas de base de datos cuyas asociaciones se muestran en Figura 1.
Copie y ejecute las siguientes sentencias para cambiar a crear una tabla de base de datos de información de tiendas por departamentos.1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105
CREATE SCHEMA retail_data; SET current_schema='retail_data'; DROP TABLE IF EXISTS STORE; CREATE TABLE STORE ( ID INT, STORECODE VARCHAR(10), STORENAME VARCHAR(100), FIRMID INT, FLOOR INT, BRANDID INT, RENTAMOUNT NUMERIC(18,2), RENTAREA NUMERIC(18,2) ) WITH (ORIENTATION = COLUMN, COMPRESSION=MIDDLE) DISTRIBUTE BY REPLICATION; DROP TABLE IF EXISTS POS; CREATE TABLE POS( ID INT, POSCODE VARCHAR(20), STATUS INT, MODIFICATIONDATE DATE ) WITH (ORIENTATION = COLUMN, COMPRESSION=MIDDLE) DISTRIBUTE BY REPLICATION; DROP TABLE IF EXISTS BRAND; CREATE TABLE BRAND ( ID INT, BRANDCODE VARCHAR(10), BRANDNAME VARCHAR(100), SECTORID INT ) WITH (ORIENTATION = COLUMN, COMPRESSION=MIDDLE) DISTRIBUTE BY REPLICATION; DROP TABLE IF EXISTS SECTOR; CREATE TABLE SECTOR( ID INT, SECTORCODE VARCHAR(10), SECTORNAME VARCHAR(20), CATEGORYID INT ) WITH (ORIENTATION = COLUMN, COMPRESSION=MIDDLE) DISTRIBUTE BY REPLICATION; DROP TABLE IF EXISTS CATEGORY; CREATE TABLE CATEGORY( ID INT, CODE VARCHAR(10), NAME VARCHAR(20) ) WITH (ORIENTATION = COLUMN, COMPRESSION=MIDDLE) DISTRIBUTE BY REPLICATION; DROP TABLE IF EXISTS FIRM; CREATE TABLE FIRM( ID INT, CODE VARCHAR(4), NAME VARCHAR(40), CITYID INT, CITYNAME VARCHAR(10), CITYCODE VARCHAR(20) ) WITH (ORIENTATION = COLUMN, COMPRESSION=MIDDLE) DISTRIBUTE BY REPLICATION; DROP TABLE IF EXISTS DATE; CREATE TABLE DATE( ID INT, DATEKEY DATE, YEAR INT, MONTH INT, DAY INT, WEEK INT, WEEKDAY INT ) WITH (ORIENTATION = COLUMN, COMPRESSION=MIDDLE) DISTRIBUTE BY REPLICATION; DROP TABLE IF EXISTS PAYTYPE; CREATE TABLE PAYTYPE( ID INT, CODE VARCHAR(10), TYPE VARCHAR(10), SIGNDATE DATE ) WITH (ORIENTATION = COLUMN, COMPRESSION=MIDDLE) DISTRIBUTE BY REPLICATION; DROP TABLE IF EXISTS SALES; CREATE TABLE SALES( ID INT, POSID INT, STOREID INT, DATEKEY INT, PAYTYPE INT, TOTALAMOUNT NUMERIC(18,2), DISCOUNTAMOUNT NUMERIC(18,2), ITEMCOUNT INT, PAIDAMOUNT NUMERIC(18,2) ) WITH (ORIENTATION = COLUMN, COMPRESSION=MIDDLE) DISTRIBUTE BY HASH(ID); DROP TABLE IF EXISTS FLOW; CREATE TABLE FLOW ( ID INT, STOREID INT, DATEKEY INT, INFLOWVALUE INT ) WITH (ORIENTATION = COLUMN, COMPRESSION=MIDDLE) DISTRIBUTE BY HASH(ID);
- Cree una tabla externa, que se utiliza para identificar y asociar los datos de origen en OBS.
- <obs_bucket_name> indica el nombre del bucket de OBS correspondiente a la región donde se encuentra DWS. Para obtener más información sobre las regiones admitidas, consulte Regiones admitidas. El bucket de OBS y los datos de ejemplo se han preestablecido en el sistema y no es necesario crearlos. En este manual, se utiliza la región CN-Hong Kong y se establece <obs_bucket_name> en dws-demo-ap-southeast-1. No se puede acceder a los datos de bucket de OBS entre regiones. Por ejemplo, si el clúster se encuentra en CN-Hong Kong, no puede establecer <obs_bucket_name> en el nombre de bucket de otra región.
- Reemplace <Access_Key_Id> y <Secret_Access_Key> con los valores reales obtenidos en Preparativos.
- El uso de AK y SK codificadas de forma rígida (hard-coded) o en texto plano representa un riesgo de seguridad. Por seguridad, encripte su AK/SK y guárdelas en el archivo de configuración o en las variables de entorno.
- Si aparece el mensaje "ERROR: schema "xxx" does not exist Position" al crear una tabla externa, significa que el esquema no existe. Realice el paso anterior para crear un esquema.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185
CREATE SCHEMA retail_obs_data; SET current_schema='retail_obs_data'; DROP FOREIGN table if exists SALES_OBS; CREATE FOREIGN TABLE SALES_OBS ( like retail_data.SALES ) SERVER gsmpp_server OPTIONS ( encoding 'utf8', location 'obs://<obs_bucket_name>/retail-data/sales', format 'csv', delimiter ',', access_key '<Access_Key_Id>', secret_access_key '<Secret_Access_Key>', chunksize '64', IGNORE_EXTRA_DATA 'on', header 'on' ); DROP FOREIGN table if exists FLOW_OBS; CREATE FOREIGN TABLE FLOW_OBS ( like retail_data.flow ) SERVER gsmpp_server OPTIONS ( encoding 'utf8', location 'obs://<obs_bucket_name>/retail-data/flow', format 'csv', delimiter ',', access_key '<Access_Key_Id>', secret_access_key '<Secret_Access_Key>', chunksize '64', IGNORE_EXTRA_DATA 'on', header 'on' ); DROP FOREIGN table if exists BRAND_OBS; CREATE FOREIGN TABLE BRAND_OBS ( like retail_data.brand ) SERVER gsmpp_server OPTIONS ( encoding 'utf8', location 'obs://<obs_bucket_name>/retail-data/brand', format 'csv', delimiter ',', access_key '<Access_Key_Id>', secret_access_key '<Secret_Access_Key>', chunksize '64', IGNORE_EXTRA_DATA 'on', header 'on' ); DROP FOREIGN table if exists CATEGORY_OBS; CREATE FOREIGN TABLE CATEGORY_OBS ( like retail_data.category ) SERVER gsmpp_server OPTIONS ( encoding 'utf8', location 'obs://<obs_bucket_name>/retail-data/category', format 'csv', delimiter ',', access_key '<Access_Key_Id>', secret_access_key '<Secret_Access_Key>', chunksize '64', IGNORE_EXTRA_DATA 'on', header 'on' ); DROP FOREIGN table if exists DATE_OBS; CREATE FOREIGN TABLE DATE_OBS ( like retail_data.date ) SERVER gsmpp_server OPTIONS ( encoding 'utf8', location 'obs://<obs_bucket_name>/retail-data/date', format 'csv', delimiter ',', access_key '<Access_Key_Id>', secret_access_key '<Secret_Access_Key>', chunksize '64', IGNORE_EXTRA_DATA 'on', header 'on' ); DROP FOREIGN table if exists FIRM_OBS; CREATE FOREIGN TABLE FIRM_OBS ( like retail_data.firm ) SERVER gsmpp_server OPTIONS ( encoding 'utf8', location 'obs://<obs_bucket_name>/retail-data/firm', format 'csv', delimiter ',', access_key '<Access_Key_Id>', secret_access_key '<Secret_Access_Key>', chunksize '64', IGNORE_EXTRA_DATA 'on', header 'on' ); DROP FOREIGN table if exists PAYTYPE_OBS; CREATE FOREIGN TABLE PAYTYPE_OBS ( like retail_data.paytype ) SERVER gsmpp_server OPTIONS ( encoding 'utf8', location 'obs://<obs_bucket_name>/retail-data/paytype', format 'csv', delimiter ',', access_key '<Access_Key_Id>', secret_access_key '<Secret_Access_Key>', chunksize '64', IGNORE_EXTRA_DATA 'on', header 'on' ); DROP FOREIGN table if exists POS_OBS; CREATE FOREIGN TABLE POS_OBS ( like retail_data.pos ) SERVER gsmpp_server OPTIONS ( encoding 'utf8', location 'obs://<obs_bucket_name>/retail-data/pos', format 'csv', delimiter ',', access_key '<Access_Key_Id>', secret_access_key '<Secret_Access_Key>', chunksize '64', IGNORE_EXTRA_DATA 'on', header 'on' ); DROP FOREIGN table if exists SECTOR_OBS; CREATE FOREIGN TABLE SECTOR_OBS ( like retail_data.sector ) SERVER gsmpp_server OPTIONS ( encoding 'utf8', location 'obs://<obs_bucket_name>/retail-data/sector', format 'csv', delimiter ',', access_key '<Access_Key_Id>', secret_access_key '<Secret_Access_Key>', chunksize '64', IGNORE_EXTRA_DATA 'on', header 'on' ); DROP FOREIGN table if exists STORE_OBS; CREATE FOREIGN TABLE STORE_OBS ( like retail_data.store ) SERVER gsmpp_server OPTIONS ( encoding 'utf8', location 'obs://<obs_bucket_name>/retail-data/store', format 'csv', delimiter ',', access_key '<Access_Key_Id>', secret_access_key '<Secret_Access_Key>', chunksize '64', IGNORE_EXTRA_DATA 'on', header 'on' );
- Copie y ejecute las siguientes sentencias para importar los datos de la tabla externa al clúster:
1 2 3 4 5 6 7 8 9 10
INSERT INTO retail_data.store SELECT * FROM retail_obs_data.STORE_OBS; INSERT INTO retail_data.sector SELECT * FROM retail_obs_data.SECTOR_OBS; INSERT INTO retail_data.paytype SELECT * FROM retail_obs_data.PAYTYPE_OBS; INSERT INTO retail_data.firm SELECT * FROM retail_obs_data.FIRM_OBS; INSERT INTO retail_data.flow SELECT * FROM retail_obs_data.FLOW_OBS; INSERT INTO retail_data.category SELECT * FROM retail_obs_data.CATEGORY_OBS; INSERT INTO retail_data.date SELECT * FROM retail_obs_data.DATE_OBS; INSERT INTO retail_data.pos SELECT * FROM retail_obs_data.POS_OBS; INSERT INTO retail_data.brand SELECT * FROM retail_obs_data.BRAND_OBS; INSERT INTO retail_data.sales SELECT * FROM retail_obs_data.SALES_OBS;
Se necesita algún tiempo para importar datos.
- Copie y ejecute la siguiente sentencia para crear la vista v_sales_flow_details:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
SET current_schema='retail_data'; CREATE VIEW v_sales_flow_details AS SELECT FIRM.ID FIRMID, FIRM.NAME FIRNAME, FIRM. CITYCODE, CATEGORY.ID CATEGORYID, CATEGORY.NAME CATEGORYNAME, SECTOR.ID SECTORID, SECTOR.SECTORNAME, BRAND.ID BRANDID, BRAND.BRANDNAME, STORE.ID STOREID, STORE.STORENAME, STORE.RENTAMOUNT, STORE.RENTAREA, DATE.DATEKEY, SALES.TOTALAMOUNT, DISCOUNTAMOUNT, ITEMCOUNT, PAIDAMOUNT, INFLOWVALUE FROM SALES INNER JOIN STORE ON SALES.STOREID = STORE.ID INNER JOIN FIRM ON STORE.FIRMID = FIRM.ID INNER JOIN BRAND ON STORE.BRANDID = BRAND.ID INNER JOIN SECTOR ON BRAND.SECTORID = SECTOR.ID INNER JOIN CATEGORY ON SECTOR.CATEGORYID = CATEGORY.ID INNER JOIN DATE ON SALES.DATEKEY = DATE.ID INNER JOIN FLOW ON FLOW.DATEKEY = DATE.ID AND FLOW.STOREID = STORE.ID;
Paso 2: Análisis del estado operativo
A continuación se utiliza la consulta estándar de información de venta minorista de grandes almacenes como ejemplo para demostrar cómo realizar una consulta de datos básica en DWS.
Antes de consultar datos, ejecute el comando Analyze para generar estadísticas relacionadas con la tabla de la base de datos. Los datos estadísticos se almacenan en la tabla del sistema PG_STATISTIC y son útiles cuando se ejecuta el planificador, que le proporciona un plan de ejecución de consultas eficiente.
A continuación se muestran ejemplos de consultas:
- Consulta de los ingresos por ventas mensuales de cada tienda
Copie y ejecute las siguientes sentencias para consultar los ingresos totales de cada tienda en un mes determinado:
1 2 3 4 5 6 7 8
SET current_schema='retail_data'; SELECT DATE_TRUNC('month',datekey) AT TIME ZONE 'UTC' AS __timestamp, SUM(paidamount) AS sum__paidamount FROM v_sales_flow_details GROUP BY DATE_TRUNC('month',datekey) AT TIME ZONE 'UTC' ORDER BY SUM(paidamount) DESC;
- Consulta de los ingresos por ventas y la relación precio-alquiler de cada tienda
Copie y ejecute la siguiente sentencia para consultar los ingresos por ventas y la relación precio-alquiler de cada tienda:
1 2 3 4 5 6 7 8 9 10
SET current_schema='retail_data'; SELECT firname AS firname, storename AS storename, SUM(paidamount) AS sum__paidamount, AVG(RENTAMOUNT)/SUM(PAIDAMOUNT) AS rentamount_sales_rate FROM v_sales_flow_details GROUP BY firname, storename ORDER BY SUM(paidamount) DESC;
- Análisis de los ingresos por ventas de cada ciudad
Copie y ejecute la siguiente sentencia para analizar y consultar los ingresos por ventas de todas las provincias:
1 2 3 4 5 6 7
SET current_schema='retail_data'; SELECT citycode AS citycode, SUM(paidamount) AS sum__paidamount FROM v_sales_flow_details GROUP BY citycode ORDER BY SUM(paidamount) DESC;
- Análisis y comparación de la relación precio-alquiler y la tasa de conversión del flujo de clientes de cada tienda
1 2 3 4 5 6 7 8 9
SET current_schema='retail_data'; SELECT brandname AS brandname, firname AS firname, SUM(PAIDAMOUNT)/AVG(RENTAREA) AS sales_rentarea_rate, SUM(ITEMCOUNT)/SUM(INFLOWVALUE) AS poscount_flow_rate, AVG(RENTAMOUNT)/SUM(PAIDAMOUNT) AS rentamount_sales_rate FROM v_sales_flow_details GROUP BY brandname, firname ORDER BY sales_rentarea_rate DESC;
- Análisis de marcas en la industria minorista
1 2 3 4 5 6 7 8
SET current_schema='retail_data'; SELECT categoryname AS categoryname, brandname AS brandname, SUM(paidamount) AS sum__paidamount FROM v_sales_flow_details GROUP BY categoryname, brandname ORDER BY sum__paidamount DESC;
- Consulta de la información de ventas diarias de cada marca
1 2 3 4 5 6 7 8 9 10 11
SET current_schema='retail_data'; SELECT brandname AS brandname, DATE_TRUNC('day', datekey) AT TIME ZONE 'UTC' AS __timestamp, SUM(paidamount) AS sum__paidamount FROM v_sales_flow_details WHERE datekey >= '2016-01-01 00:00:00' AND datekey <= '2016-01-30 00:00:00' GROUP BY brandname, DATE_TRUNC('day', datekey) AT TIME ZONE 'UTC' ORDER BY sum__paidamount ASC LIMIT 50000;
