i was trying to solve a problem which just looks like the code written below, but from lack of knowledge and reading through the sqlalchemy documentation, i do not really find any solution on how to solve my problem, yet.
Objective:
Get summed value of sales_in_usd if year in year_column is same
What I got so far is by debugging and reading a bit through stackoverflow and documentations, google by using following query:
session.query(fact_corporate_sales, Company, Sales,
Time, Sector, func.sum(Sales.sales_in_usd).label('summary')).\
join(Sales).\
join(Time).\
join(Company).\
join(Segment).\
order_by(Time.year.desc()).\
filter(Company.company_name.like(filtered)).\
group_by(fact_corporate_sales.fact_cps_id, Company.company_name,fact_corporate_sales.cps_id).\
all()
And well the fact_cps_id is unique in the fact_table and the same table stores, the keys of the dimension tables as well..
I have a fact table which stores 4 foreign keys from 4 dimension tables.
fact_cps_id company_id sales_id time_id sector_id
1 4 2 1 2
2 4 1 1 3
3 4 3 2 1
4 4 2 2 4
5 4 4 3 2
6 4 99 1 1
dim_company
company_id company_name
1 Nike
2 Adidas
3 Puma
4 Reebok
dim_segment
segment_id segment_nom
1 basketball
2 running
3 soccer
4 watersports
dim_time
time_id quarter year
1 1 2013
2 2 2013
3 1 2014
4 3 2014
dim_sales
sales_id sales_in_euro
1 2000
2 3200
3 1400
4 1590
.. ..
99 1931
So basically, as you can see in the table and query what I was trying to do was summing up all sales from the as example dim_Time.year <- from the same year.
If we look into the fact_table we can see, that we have time_id = 1 three times, here. So those values could be summed up and displayed as a summary.
I know from standard SQL that it was possible by using group by and aggregate function sum.
My result(time_id is only for help therefore was no output):
13132.0 <- time_id = 1
21201.0 <- time_id = 2
23923.0 <- time_id = 1
31232.0 <- time_id = 99
32021.0 <- time_id = 2
32342.0 <- time_id = 1
131231.0 <- time_id = 4
I printed the actual query into the console and got this [had to remove .all(), because 'list' has no attribute called 'statement']:
SELECT fact_corporate_sales.cps_fact_id, fact_corporate_sales.cps_id,
fact_corporate_sales.company_id, fact_corporate_sales.time_id, fact_corporate_sales.segment_id, sum(dim_corporate_sales.sales_in_usd) AS summary
FROM fact_corporate_sales INNER JOIN dim_corporate_sales ON dim_corporate_sales.cps_id = fact_corporate_sales.cps_id INNER JOIN dim_time ON dim_time.time_id = fact_corporate_sales.time_id INNER JOIN dim_company ON dim_company.company_id = fact_corporate_sales.company_id INNER JOIN dim_segment ON dim_segment.segment_id = fact_corporate_sales.segment_id
WHERE dim_company.company_name LIKE %s GROUP BY fact_corporate_sales.cps_fact_id ORDER BY dim_time.year DESC
And if I want to group by for example dim_time.Year only..I get following response from mysql or console
Error Code: 1055. Expression #1 of SELECT list is not in GROUP BY clause and contains nonaggregated column 'db.fact_corporate_sales.fact_cps_id' which is not functionally dependent on columns in GROUP BY clause; this is incompatible with sql_mode=only_full_group_by
The solution was only to execute following sql:
engine.execute("SET sql_mode='';")
As the response of my failed query was:
"this is incompatible with sql_mode=only_full_group_by"
I had to disable the sql_mode and so did I and got my result.
Related
I want to have the sum of the beginning inventory of the entire year. The beginning inventory is based of the end_inventory of another month. The beginning_inventory_id contains the ID of another row which points to the end_inventory. How do I properly get the sum of the beginning_inventory of a certain year when it's based of another row's end_inventory. I have the following table
id
time_period
beginning_inventory_id
end_inventory
gross_sales
1
2020-09-01
null
1000
500
2
2020-10-01
1
2000
500
3
2020-11-01
2
3000
500
4
2020-12-01
3
4000
500
5
2021-01-01
4
5000
500
I have the following SQL query
SELECT SUM(a.gross_sales) as gross_sales, SUM(a.end_inventory) as end_inventory,
(SELECT SUM(b.end_inventory) FROM fs_summary as b WHERE a.beginning_inventory_id = b.id) as beginning_inventory
FROM fs_summary as a
WHERE YEAR(a.time_period) = 2020
Output I would like to generate is:
beginning_inventory = 6000
end_inventory = 10000
gross_sales = 2000
Instead, I am getting null on the beginning_inventory.
Any help would be great!
I am Assuming that you want to retrieve data from 1 table with self join.
SELECT SUM(a.gross_sales),SUM(a.end_inventory),SUM(b.end_inventory)
FROM fs_summary a, fs_aummary b
WHERE b.id=a.beginning_inventory_id AND YEAR(a.time_period) = 2020
using self join can help you in this situation
EDIT: You can also write this script as,
SELECT SUM(a.gross_sales),SUM(a.end_inventory),SUM(b.end_inventory)
FROM fs_summary a
INNER JOIN fs_aummary b
ON b.id=a.beginning_inventory_id
WHERE YEAR(a.time_period) = 2020
Using self-join SQL you can achieve your result instead of sub-queries.
You should specify the same table with two different names. Your query looks as below
select sum(virtual_tb.end_inventory) as 'beginning_inventory', sum(org_tb.end_inventory) as 'end_inventory', sum(org_tb.gross_sales) as 'gross_sales'
from fs_summary org_tb left join fs_aummary virtual_tb on (virtual_tb.beginning_inventory_id = org_tb.id)
where year(org_tb.time_period) = 2020;
(Approx Output)
beginning_inventory
end_inventory
gross_sales
6000
10000
2000
I’m a mysql newbie, recently installed mariadb to work on a project.
I have one table of many ITEMS, which are in various categories (catnum), and another table, STATUS, showing items (by id#) and their current status, either A or B.
I need to write a query that lists all of the categories (by catnum) and the total of all A’s and B’s in each category, something like this:
Desired result:
catnum statA statB
1001 22 15
1002 0 12
1003 14 8
1004 3 37
1005 24 0
1006 0 1
1007 47 5
etc
The ITEMS table looks like this:
itemid catnum
1 1205
2 1008
3 1010
4 1150
5 1782
6 1553
7 1004
etc
The STATUS table looks like this:
itemid stat
60 A
302 A
95 B
122 B
8 B
6 A
46 B
etc
The itemid in ITEMS is auto_increment, in case that matters.
I know (or think I know) that I need to use the following in some combination:
count(status.stat) or count(status.stat = A)
where items.itemid = status.itemid
where stat = A (then B)
group by catnum.
In some combinations I got error saying “Unknown column 'status.itemid' in 'having clause'” or other clause, despite that it exists. Why is that?
The closest I have gotten is to show each category and both status columns properly labeled but the number of B status items was incorrect, just a repeat of number of A status items.
SELECT
items.catnum,
count(status.stat=1) AS statA,
count(status.stat=2) AS statB
FROM
status
INNER JOIN
items
WHERE
items.itemid = status.itemid
GROUP BY
catnum;
(ALSO tried with ON instead of WHERE, same result, statB totals were wrong.)
I have explored self joins, inner joins, left/right joins, unions, subquery, and other techniques but I can’t seem to get to what I want. It seems like this must be a really common general query, but I can’t seem to find the right search terms to find it online. Any guidance would be appreciated.
Your query as it currently stands will simply return a COUNT of all the items in STATUS which have a given catnum. This is why the values for statA and statB are the same. What you need to do is SUM the occurrences of each status value. I've made a small SQLFiddle demo that shows this query in action:
SELECT
items.catnum,
SUM(status.stat='A') AS statA,
SUM(status.stat='B') AS statB
FROM items
JOIN status
ON items.itemid = status.itemid
GROUP BY items.catnum
Output (for the demo data):
catnum statA statB
1004 1 1
1008 2 1
1010 0 2
Note that in MySQL a boolean expression (e.g. status.stat='A') evaluates to 1 if true, 0 if false, so it can be summed directly.
I want to create a query to get the total number of produced products for each day in Microsoft Access.
Here are the few rows of my table as a sample:the table's name is Orders
ordernumber number of products Date
100 2 11-May-16
101 1 11-May-16
121 2 24-May-16
122 3 24-May-16
131 1 25-May-16
105 3 11-May-16
127 1 24-May-16
135 2 25-May-16
The desired output is :
TotalNoProducts Date
6 11-May-16
6 24-May-16
3 25-May-16
This is one of the more basic aggregate queries:
SELECT SUM([number of products]) As TotalNoProducts, CDate(Int([Date])) As TheDate
FROM Orders
GROUP BY CDate(Int([Date]))
Note that you can also build this query through the query builder, which is usually easier for beginners than using SQL
I'm trying to join a few tables in MySQL. Our setup is a little unique so I try to explain as good as I can.
I have a table 'INVENTORY' that represents the current items on stock.
These items are stored in a table 'COMPONENT'
Components are being used in installations.
Every user can have multiple installations and the same component can be used in multiple installation as well.
To uniquely map a component to an installation, it can be assigned to a PRODUCT. a product as has a 1-1 relationship with an installation. A component is not directly related to an installation
To finally assign a product to a specific installation a mapping table COMPOMENT_PRODUCT is used.
Example:
A component is like a part, lets say a screw. This screw is used in a computer. The very same screw can be used on multiple computers. But each computer can only be used on one specific installation.
TABLE COMPOMENT_PRODUCT
COMPOMENT_ID PRODUCT_ID
1 1
1 2
2 1
2 2
So we have the components C1 and C2 relevant for two installations.
TABLE INVENTORY
COMPOMENT_ID INSTALLATION_ID ON_STOCK
1 1 5
1 2 2
What I want to achieve
Now, I want to retrieve the inventory state for all components. But, not every component has an inventory record. In these cases, the ON_STOCK value from the inventory shall be NULL
That means, for this example I'd expect the following results
COMPOMENT_ID PRODUCT_ID ON_STOCK
1 1 5
1 2 2
2 1 NULL
2 2 NULL
But executing this query:
SELECT DISTINCT
COMPONENT_PRODUCT.COMPONENT_ID,
COMPONENT_PRODUCT.PRODUCT_ID,
INVENTORY.ON_STOCK
FROM INVENTORY
RIGHT JOIN COMPONENT_PRODUCT ON COMPONENT_PRODUCT.COMPONENT_ID =
INVENTORY.COMPONENT_ID
returns the following resultset:
COMPONENT_ID PRODUCT_ID ON_STOCK
1 1 5
1 2 5
1 1 2
1 2 2
2 1 (null)
2 2 (null)
Now, my next thought was, "of course, this is how joins behave, okay I need to group the results". But the way SQL works, the aggregation is not entirely predictable. SO when I
GROUP BY COMPONENT_PRODUCT.COMPONENT_ID,COMPONENT_PRODUCT.PRODUCT_ID
I get this result:
COMPONENT_ID PRODUCT_ID ON_STOCK
1 1 5
1 2 5
2 1 (null)
2 2 (null)
I have prepared a Fiddle here: http://sqlfiddle.com/#!9/71ca87
What am I forgetting here? Thanks in advance for any pointers.
Try this query -
SELECT DISTINCT
COMPONENT_PRODUCT.COMPONENT_ID,
COMPONENT_PRODUCT.PRODUCT_ID,
INVENTORY.ON_STOCK
FROM INVENTORY
RIGHT JOIN COMPONENT_PRODUCT ON COMPONENT_PRODUCT.COMPONENT_ID =
INVENTORY.COMPONENT_ID
AND COMPONENT_PRODUCT.PRODUCT_ID = INVENTORY.INSTALLATION_ID
I need to filter a table in mysql but can't get past the beginning.
The table has 2 fields:
ID_house house_feature
1 1
1 2
1 4
1 5
2 1
2 3
2 4
3 1
3 2
3 3
I need to filter this table using the following parameters:
house feature = 1
AND
house feature = 2
AND
house feature = 3
So that I get all houses with the requested feature.
I already tried to create something similar to this:
SELECT *
FROM houses
WHERE
house_feature = 1
AND
house_feature = 2
AND
house_feature = 3
But it doesn't work as I expected.
Is there a way to get this result with MySQL?
It seems that I acn filter the table using only the OR operator but this way I can't get the right result.
Thanks in advance for any help.
tony
You can do so ,by matching the distinct count of features per house ,so the house with exactly these 3 features will be returned
SELECT *
FROM t
WHERE
house_feature IN(1 ,2,3)
group by ID_house
having count(distinct house_feature) = 3
Demo