Join multiple tables in Microsoft SQL Server where there is only one line match from table 1 and multiple lines from table 2 and 3 - sql

I am stuck on something, which I have never used in my 10 years of SQL. I thought it would be useful if there was someway of doing this. Firstly I am running SQL Server Express (latest free version) on Windows. To talk to the database I am using SSMS.
There are three tables/queries.
1 table (A) has one data value I want to pull through.
2 tables (B)/(C) have multiple values.
Column common to all tables is CAMPAIGN NAME
Column common to (B)/(C) is PRODUCT NAME
This is an example of the data:
OUTPUT GOAL
I have tried the following:
UNION ALL (but this does not assist when I want to calculate AMOUNT - MARKETING - TOTAL INVESTMENT
I tried PARTITION (but I simple could now get it to work.
If I use joins, it brings through a head count / total investment and marketing cost per product, which when using SUM brings through the incorrect values for head count / total investment and marketing cost vs total amount, quantity.
I tried splitting the costs based on Quantity / Total Quantity or Amount / Total Amount, but the cost associated with the product is not correct or directly relating to the product this way.
Am I trying to do something impossible, or is there a way to do this in SQL?

The following comes pretty close to what you want:
select . . . -- select the columns you want here
from a join
b
on b.campaign_name = a.campaign_name join
c
on c.campaign_name = b.campaign_name and
c.product_name = b.product_name;
This produces a result set with a separate row for each campaign/product.

Related

Generate dynamic date columns in a SELECT query SQL

First of I've got a table like this:
vID
bID
date
type
value
1
100
22.01.2021
o
250.00
1
110
25.01.2021
c
100.00
2
120
13.02.2021
o
400.00
3
130
20.02.2021
o
475.00
3
140
11.03.2022
c
75.00
1
150
15.03.2022
o
560.00
To show which values were ordered(o) and charged(c) per Month, I have to like 'generate' columns for each month both ordered and charged in a MSSQL SELECT query.
Here is an example table of what I want to get:
vID
JAN2021O
JAN2021C
FEB2021O
FEB2021C
…
MAR2022O
MAR2022C
1
250.00
100.00
560.00
2
400.00
3
475.00
75.00
I need a posibility to join it in a SQL SELECT in addition to some other columns I already have.
Does anyone has an idea and could help me please?
The SQL language has a very strict requirement to know the number of columns in the results and the type of each column at query compile time, before looking at any data in the tables. This applies even to SELECT * and PIVOT queries, where the columns are still determined at query compile time via the table definition (not data) or SQL statement.
Therefore, what you want to do is only possible in a single query if you want to show a specific, known number of months from a base date. In that case, you can accomplish this by specifying each column in the SQL and using date math with conditional aggregation to figure the value for each of the months from your starting point. The PIVOT keyword can help reduce the code, but you're still specifying every column by hand, and the query will still be far from trivial.
If you do not have a specific, known number of months to evaluate, you must do this over several steps:
Run a query to find out how many months you have.
Use the result from step 1 to dynamically construct a new statement
Run the statement constructed in step 2.
There is no other way.
Even then, this kind of pivot is usually better handled in the client code or reporting tool (at the presentation level) than via SQL itself.
It's not as likely to come up for this specific query, but you should also be aware there are certain security issues that can be raised from this kind of dynamic SQL, because some of the normal mechanisms to protect against injection issues aren't available (you can't parameterize the names of the source columns, which are dependent on data that might be user-generated) as you build the new query in step 2.

TOTAL vs Aggr in QlikView

I'm trying to understand how TOTAL and Aggr work in QlikView. Could someone please explain the difference between the two examples below, and if possible please illustrate with a SQL query?
Example1:
Max({<Field1=>} Aggr(Sum({<Field2={'Value'}, Field1=>} StuffCount), Field1))
Example2:
Max({<Field1=>} TOTAL Aggr(Sum({<Field2={'Value'}, Field1=>} StuffCount), Field1))
Not sure what you mean with and SQL query in this example. Anyway, imagine you have this list of Customers (CustomerID) and Sales (Sales):
CustomerID/ Sales
Customer1 25
Customer2 20
Customer1 10
Customer1 5
Customer1 20
Customer3 30
Customer2 30
Then you want to show it on a pivot table with dimension CustomerID and two expressions:
Max(Aggr(Sum(Sales), CustomerID)) // this will show 60 for the first customer, 50 for the second and 30 for the third one
Max(TOTAL Aggr(Sum(Sales),CustomerID)) //this will show 60 in every row of your table (which is the maximum sum of sales among all customers)
So basically AGGR creates a temporal list of whatever you put in the first function input (in this case sum(Sales)) using the dimension of the second (CustomerID). Then you can perform operations on that list (such as Max, Min, Avg...). If you write TOTAL and use the expression in a pivot table, then you 'ignore' the dimensions that might be affecting the operations.
Hope it helps
TOTAL keyword is useful in charts/pivot tables. It applies the same calculation on every datapoint in the chart/pivot, with independence of dimentions.
Therefore - if you put your expression into pivot table - 1st option may display different values per cell (if the Aggr is rellevant) when the 2nd will result in same values.
Aggr function allows making double aggregations (avg of sum, max of count etc..) on different group by bases.

Confused on this assignment, any guidance?

The Problem:
First create a table called amttopay that has three fields: rec_no, idno and amt (make amount a numeric field that can hold 3 decimal places. You are also going to use a copy of the donor table for this assignment. Take in a number that matches an idno on the donor table. Check the yrgoal for that record. If it is larger than 500 then double it to create a new goal and write four records on the amttopay table containing the quarterly payment number (1 through 4), the idno, and the quarterly amount to pay to achieve the new goal. If it is not larger than 500 then add 50% to the goal to make the new goal and process it by writing the four records with the same information.
I've created the table, and I understand I've gotta write PL/SQL code to accomplish this, but what I'm not understanding is how the question is worded.
"If it is larger than 500 then double it to create a new goal and write four records on the amttopay table containing the quarterly payment number (1 through 4), the idno, and the quarterly amount to pay to achieve the new goal."
What does that mean? How would I go about bringing logic into this?
Thanks so much for the help.
Assuming you are trying to actually understand the question, this is how you would do it:
Break your statement into parts:
Check the yrgoal for that record.
If it is larger than 500 then
double it to create a new goal
and write four records on the amttopay table containing the quarterly payment number (1 through 4), the idno, and the quarterly amount to pay to achieve the new goal.
If it is not larger than 500 then
add 50% to the goal to make the new goal
and process it by writing the four records with the same information.
Simplified, this gives the following:
Create new record
if yrgoal>500 then
double yrgoal
Create 4 records with idnoand the quarterly amount
else
yrgoal * 1.5
Create 4 records as before
The rest is up to you, of course …

counting and numbering in a select statement in Access SQL

Could you please help me figuring out how to accomplish the following.
I have a table containing the number of products available between one date and another as per below:
TABLE MyProducts
DateProduct ProductId Quantity Price
26/02/2016 7 2 100
27/02/2016 7 3 100
28/02/2016 7 4 100
I have created a form where users need to select a date range and the number of products they are looking for (in my example, the number of products is going to be 1).
In this example, let's say that a user makes the following selection:
SELECT SUM(MyProducts.Price) As TotalPrice
FROM MyProducts WHERE MyProducts.DateProduct
Between #2/26/2016# And #2/29/2016#-1 AND MyProducts.Quantity>=1
Now the user can see the total amount that 1 product costs: 300
For this date range, however, I want to allow users to select from a combobox also the number of products that they can still buy: if you give a look at the Quantity for this date rate, a user can only buy a maximum of 2 products because 2 is the lowest quantity available is in common for all the dates listed in the query.
First question: how can I feed the combobox with a "1 to 2" list (in this case) considering that 2 is lowest quantity available in common for all the dates queried by this user?
Second question: how can I manage the products that a user has purchased.
Let's say that a user has purchased 1 product within this date range and a second user has purchased for the very same date range the same quantity too (which is 1) for a total of 2 products purchased already in this date range. How can I see that for this date rate and giving this case the number of products actually available are:
DateProduct ProductId Quantity Price
26/02/2016 7 0 100
27/02/2016 7 1 100
28/02/2016 7 2 100
Thank you in advance and please let me know should you need further information.
You could create a table with an integer field counting from 1 to whatever max qty you could expect. Then create a query that will only return rows from your new table up to the min() qty in the MyProducts table. Use that query as the control source of your combobox.
EDIT: You will actually need two queries. The first should be:
SELECT Min(MyProducts.Quantity) AS MinQty FROM MyProducts;
which I called "qryMinimumProductQty". I create the table called "Numbering" with a single integer field called "Sequence". The second query:
SELECT Numbering.Sequence FROM Numbering, qryMinimumProductQty WHERE Numbering.Sequence<=qryMinimumProductQty.MinQty;
AFAIK there is no Access function/feature that will fill in a series of numbers in a combobox control source. You have to build the control source yourself. (Anyone with more VBA experience might have a solution to solve this, but I do not.)
It makes me ache thinking of an entire table with a single integer column only being used for a combobox though. A simpler approach to the combobox would just to show the qty available in a control on your form, give an unbound text box for the user to enter their order qty, and add a validation rule to stop the order and notify them if they have chosen a number greater than the qty on hand. (Just a thought)
As for your second question, I don't really understand what you're looking for either. It sounds like there may be another table of purchases? It should be a simple query to relate MyProducts to Purchases and take the difference between your MyProducts!qty and the Purchases!qty. If you don't have a table to store Purchases, it might be warranted based on my cursory understanding of your system.

ms sql Query for POS item sales

I have a SQL question regarding POS system item sales data. In the database, there is a "Totals" table. In that table, contains various records identified by the "TtlType" field. I'm working with 2 types. Values 11, which is the Item POS Sales, and 12, which is the Item Cost Sales.
When I do my SQL Query, i'm doing something along the lines of
SELECT ItemNumber,
SUM(ItemCount),
SUM(ItemAmount)
FROM Totals
WHERE TtlType = 11
AND Date = 8/1/2012
etc.
I'd like to also include TtlType 12. How can I merge all of the data into one row?
If I change my WHERE to include TtlType 11 & 12, I get 2 seperate rows for each menu item. The first one being TtlType 11 which is the Sell Price, and the next being 12 which is the cost. BOTH TtlType use the SAME field names to record information (ItemCount, ItemAmount)
I hope i explained this well enough. When I use the GROUP BY, I still get the same results.
I'm not sure I understand your data structure fully, or the significance of ItemNumber.
However, you don't need a GROUP BY to do SUM as you already know, but including ItemNumber in your SELECT & GROUP BY will definitely cause you to have duplicate rows as it will be grouped on that column.
You shouldn't have any issues with the two SUM functions with just
SELECT SUM(ItemCount), SUM(ItemAmount) FROM Totals WHERE TtlType IN (11,12)
AND Date = 8/1/2012