Counting different combinations - sql-server

I have a data set that looks like this (user ID in one column and medicine name in another - users can have multiple rows if they use multiple medicines). I want to find the most common combinations of medicines used e.g. 5 people use medicine a and b and 4 people use medicine a,b and c
Expected output
Data frame

You have to count unique number of users per medicine
SELECT medicine
, count(unique user_id) as uniq_users
, count(user_id) as total_users
FROM your_table_name
GROUP BY medicine
list of medicines per user
SELECT user_id
, medicine
FROM your_table_name
GROUP BY user_id
, medicine
However, if this is the table structure, it's very wrong.. you should read more about "database normal forms"

Related

Query on at least and not present in SQL table

I have two queries:
Query the id number of the students who at least enrolled subj1 and subj2 courses (I do not know how to code for at least)
Query the id number, name, and age of the students who did not enroll subj2 course.
I coded something as below - which returns an empty table even though I should get some values.
Select sno, sname, age
from student
where not exists (select cno from course where cno ='C2');
I'm assuming you have a table connecting students with courses in a many-to-many, so that each student can enroll in more than one course and each course can contain multiple students.
So for the sake of this example, let's call it StudentsToCourses.
This table should contain the student id and the course id, and it's primary key should contain the combination of both it's columns.
So the first query would be something like (to get student numbers enrolled into at least one of the two courses):
SELECT sno
FROM StudentToCourses
WHERE cno IN ('C1', 'C2')
or this (to get students enrolled into both courses):
SELECT sno
FROM StudentToCourses
WHERE cno IN ('C1', 'C2')
GROUP BY sno
HAVING COUNT(DISTINCT cno) = 2
Note that the subquery in the EXISTS operator is correlated to the main query using the student number.
The second query is almost the same as the first one, except instead of IN you use =, and instead of EXISTS you use NOT EXISTS.
Since this seems like a homework question, I'll leave it up to you to write the code, otherwise you will not learn anything from this.

How to store multiple contact numbers per employee

I want to add multiple values to a single record. For example dbo.TblEmp
has columns like ID, Name, & ContactNo, and a employee can have 2 or 3 contact numbers.
Like:
ID Name ContactNo
0001 John 914587962
997896547
You can create an additional table name EmployeeCommunication and using foreign keys you can define a relation with Employee in TblEmp to EmployeeCommunication table where ContactNo is stored

break normalization rules , creat table /view from muliple tables

I have a question and am not sure if this is the correct forum to post it .
I have two tables, StudentTable and CourseTable, where each student takes more than one course.
Example: Student1 takes 2 courses: (C1, C2).
Student2 takes 3 courses (C1, C2, C3).
I need to create a table/view that contains student information from StudentTable, plus all the courses and the score for each course from CourseTable - in one row.
Example:
Row1= Student1_Id, C1_code, C1_name, C1_Score, C2_code, C2_name, C2_Score
Row2=
Student2_Id, C1_code, C1_name, C1_Score, C2_code, C2_name, C2_Score, C3_code, C3_name, C3_Score
Since Student1 has just two courses, I should enter NULL in 'Course 3 fields'
My struggle is in the insert statement. I tried the following but it showed an error.
Insert Into Newtable
( St_ID, C1_code,c1_name, C1_Score ,C2_code ,C2_name,C2_score,C3_code ,C3_name,C3_score)
Select
(Select St_ID from StudentTable)
,
(Select C_code,c_name,c_Score
from Coursetable,SudentTable
where course.Stid =Studet.stid)
,
(Select C_code,c_name,c_Score
from course ,student
where course.Stid =Studet.stid ),
(Select C_code,c_name,c_Score
from course ,student
where course.Stid =Studet.stid );
I'm fully aware that the New table/View will break the rules of normalization, but I need it for a specific purpose.
I tried also the PIVOT BY functionality but no luck with it.
FYI, I'm not expert in SQL syntax. I just know the basics.
I will be great full for any helpful suggestions to try.
I added My DB structure so you can have better Idea
First Table is Member table which Represent Students Information .The fields in this table are
member_sk (PrimaryKey), full_or_part_time, gender, age_at_entry, age_band_at_entry, disability, ethnicity,
widening_participation_level, nationality
Second Table is Modules table which include the Courses' scores that Student took .
The fields in this table are
Module_result_k(Primary Key), member_sk(Foreign key to connect to Member table), member_stage_sk ,module_k(Foreign key to connect to Module table), module_confirmed_grade_src, credit_or_result
Third Table is AllModuleInfo which is include general information for each course .The fields in this table are
Module_k (Primary key), module_name ,module_code, Module_credit, Module stage.
The New table that I will create has the following fields
member_sk (PrimaryKey), full_or_part_time, gender, age_at_entry, age_band_at_entry, disability, ethnicity,
widening_participation_level, nationality " This will be retrieved from Member table"
Also will include
Module 1_name ,module1_code, Module1_credit, Module1_ stage, member1_stage_sk , module1_confirmed_grade_src, credit1_or_result
Module 2_name ,module2_code, Module2_credit, Module2_ stage, member2_stage_sk , module2_confirmed_grade_src, credit2_or_result
-
-
-
I will repeat this fields 14 times which is equal to Maximum courses number that any of the students took.
//// I hope now my questions become more clear

Best structure for inventory database

I want to create a small database for my inventory but I have some problems on picking a structure. The inventory will be updated daily at the end of the day.
The problem I am facing is the following.
I have a table for my products, having an
id, name, price, quantity.
Now I have another table for my sales, but there is my problem. What kind of fields do I need to have. At the end of the day I want to store a record like this:
20 product_x $ 5,00 $ 100,-
20 product_y $ 5,00 $ 100,-
20 product_z $ 5,00 $ 100,-
20 product_a $ 5,00 $ 100,-
-------------------------------------------------
$ 400,-
So how do I model this in a sales record. Do I just create a concatenated record with the product id's comma separated.
Or is there another way do model this the right way.
This is a model which supports many aspects,
Supports Sites, Locations and Warehouses etc.
Supports Categorization and Grouping
Support Generic Product (Ex. "Table Clock" and specific product "Citizen C123 Multi Alarm Clock" )
Also support Brand Variants (by various manufacturers)
Has CSM (color / size / model support) Ex. Bata Sandles (Color 45 Inch Blue color)
Product Instances with serials (such as TVs , Refrigerators etc.)
Lot control / Batch control with serial numbers.
Pack Size / UOM and UOM Conversion
Manufacturer and Brands as well as Suppliers
Also included example transaction table (Purchase order)
There are many other transaction types such as Issues, Transfers, Adjustments etc.
Hope this would help. Please let me know if you need further information on each table.
Cheers...!!!
Wajira Weerasinghe.
Sites
id
site_code
Site_name
Warehouse
id
site_id
warehouse_code
warehouse_name
Item Category
id
category_code
category_name
Item Group
id
group_code
group_name
Generic Product
id
generic_name
Product
id
product_code
category_id
group_id
brand_id
generic_id
model_id/part_id
product_name
product_description
product_price (current rate)
has_instances(y/n)
has_lots (y/n)
has_attributes
default_uom
pack_size
average_cost
single_unit_product_code (for packs)
dimension_group (pointing to dimensions)
lot_information
warranty_terms (general not specific)
is_active
deleted
product attribute type (color/size etc.)
id
attribute_name
product_attribute
id
product_id
attribute_id
product attribute value (this product -> red)
id
product_attribute_id
value
product_instance
id
product_id
instance_name (as given by manufacturer)
serial_number
brand_id (is this brand)
stock_id (stock record pointing qih, location etc.)
lot_information (lot_id)
warranty_terms
product attribute value id (if applicable)
product lot
id
lot_code/batch_code
date_manufactured
date_expiry
product attribute value id (if applicable)
Brand
id
manufacturer_id
brand_code
brand_name
Brand Manufacturer
id
manufacturer_name
Stock
id
product_id
warehouse_id, zone_id, level_id, rack_id etc.
quantity in hand
product attribute value id (if applicable) [we have 4 red color items etc.]
Product Price Records
product_id
from_date
product_price
Purchase Order Header
id
supplier_id
purchase_date
total_amount
Purchase Order Line
id
po_id
product_id
unit_price
quantity
Supplier
id
supplier_code
supplier_name
supplier_type
product_uom
id
uom_name
product_uom_conversion
id
from_uom_id
to_uom_id
conversion_rule
I'd have a table with a row per item per day - store the date, the item ID, the quantity sold, and the price sold at (store this even though it's also in the product table - if that changes, you want the value you actually sold at preserved). You can compute totals per item-day and totals per day in queries.
Tables:
create table product (
id integer primary key,
name varchar(100) not null,
price decimal(6,2) not null,
inventory integer not null
);
create table sale (
saledate date not null,
product_id integer not null references product,
quantity integer not null,
price decimal(6,2) not null,
primary key (saledate, product_id)
);
Reporting on a day:
select s.product_id, p.name, s.quantity, s.price, (s.quantity * s.price) as total
from product p, sale s
where p.id = s.product_id
and s.saledate = date '2010-12-5';
Reporting on all days:
select saledate, sum(quantity * price) as total
from sale
group by saledate
order by saledate;
A nice master report over all days, with a summary line:
select *
from (
(select s.saledate, s.product_id, p.name, s.quantity, s.price, (s.quantity * s.price) as total
from product p, sale s
where p.id = s.product_id)
union
(select saledate, NULL, 'TOTAL', sum(quantity), NULL, sum(quantity * price) as total
from sale group by saledate)
) as summedsales
order by saledate, product_id;
Try modelling your sales as a transaction - with a "header", i.e. who sold to, when sold, invoice # (if applicable), etc. and "line items", i.e. 20 * product_x # $5 = $100. The safest approach is to avoid relying upon prices etc. from the products table - as these will presumably change over time, and instead copy much of the product information (if not all) into your line item - so even when prices, item descriptions etc. change, the transaction information remains as was at the time the transaction was made.
Inventory can get quite complex to model. First you need to understand that you need to be able to tell the value of the inventory onhand based on what you paid for it. This means you cannot rely on a product table that is updated to the current price. While you might want such a table to help you figure out what to sell it for, there are tax reasons why you need to know the actual vlaue you paid for each item in the warehouse.
So first you need the product table (you might want to make sure you have an updated date column in this, it can be handy to know if your prices seem out of date).
Then you need a table that stores the actual warehouse location of each part and the price at purchase. If the items are large enough, you need a way to individually mark each item, so that you know what was taken out. Usually people use barcodes for that. This table needs to be updated to record that the part is no longer there when you sell it. I prefer to make the record inactive and have a link to my sales data to that record, so I know exactly what I paid for and what I sold each part for.
Sales should have at least two tables. One for the general information about the sale, the customername (there should also be a customer table most of the time to get this data from), the date, where it was shipped to etc.
Then a sales detail table that includes a record for each line item in the order. Include all the data you need about the part, color, size, quantity, price. This is not denormalizing, this is storing historical data. The one thing you do not want to do is rely on the prices in the product table for anything except the inital entry to this table. You do not want to do a sales report and have the numbers come out wrong becasue the product prices changed the day before.
Do not design an inventory database without consulting with an accountant or specialist in taxes. You also should do some reading on internal controls. It is easy to steal from a company undetected that has not done their work on internal controls in the database.
I think you need a table with fields showing the transaction properties per customer
OR
a table with fields - date, product(foreign), quantity - this way you'll have no problem with new products
Try multiple tables with links
table_products
id
name
table_product_sales
id
product_id
quantity
price_per
transaction_time AS DATETIME
SELECT table_product_sales.*, table_product.name
FROM table_product
JOIN table_product_sales
ON table_product_sales.product_id = table_product.id
GROUP BY DATE(transaction_time)
Haven't tried it but will something like that work? That allows you to keep each transactions separate so you can query things like average number sold per sale, total sold per date, total sales each day, etc.

Storing multiple employee IDs in one column of data

Web app is being written in classic ASP with a MSSQL backend. On this particular page, the admin can select 1 or any/all of the employees to assign the project to. I'm trying to figure out a simple way to store the employee IDs of the people assigned to it in one column.
The list of employees is generated from another table and can be dynamic (firing or hiring) so I want the program to be flexible enough to change based on these table changes.
Basically need to know how to assign multiple people to a project that can later be called up on a differen page or from a different query.
Sorry for the n00bish question, but thanks!
Don't store multiple ID's in one column! Create another table with the primary key of your existing table and a single ID that you want to store. You can then insert multiple rows into this new table, creating a 1:m (one to many) relationship. For example, let's look at an order table:
order:
order_id
order_date
and I have a product table...
product:
product_id
product_name
Now, you could go down the road of adding a column to order that let you list the products in the order, but that would be bad form. What you want instead is something like..
order_item:
order_item_id
order_id
product_id
quantity
unit_price
You can then perform a join to get all of the products for a particular order...
select
product.*
from orders
inner join order_item on order_item.order_id = order.order_id
inner join product on product.product_id = order_item.product_id
where orders.order_id = 5
Here's an example order_id of 5, and this will get all of the products in that order.
You need to create another table that stores these values such as. So this new table would store one row for each ID, and then link back to the original record with the original records ID.

Resources