I building a blog for school i would like to display the count of comments for each thread made. However I'm a bit lost to how to achieve this goal any help would be great thank you!
i have 2 tables
CREATE TABLE `blog_message` (
`MessageID` int(30) NOT NULL AUTO_INCREMENT,
`Username` varchar(45) NOT NULL,
`Message` text,
`AddedDate` datetime DEFAULT NULL,
`Title` varchar(45) DEFAULT NULL,
PRIMARY KEY (`MessageID`)
)
CREATE TABLE `blog_comments` (
`CommentID` int(30) NOT NULL AUTO_INCREMENT,
`MessageID` int(30) DEFAULT NULL,
`Author` varchar(45) DEFAULT NULL,
`CommentMessage` text,
`AddedDate` datetime DEFAULT NULL,
PRIMARY KEY (`CommentID`),
KEY `blog_comments_ibfk_1` (`MessageID`),
CONSTRAINT `blog_comments_ibfk_1` FOREIGN KEY (`MessageID`) REFERENCES `blog_message` (`MessageID`)
)
my goal is
to display in a gridview
int a table format
Comment count | title | Username | Date of creation
The following is MySQL syntax, not sure what you're using. But this will return a list MessageIds and the number of comments they have.
----------------------------
| MessageId | comment_count|
----------------------------
| 1234 | 34 |
----------------------------
SELECT bm.MessageId, count(bc.CommentId) as comment_count
FROM blog_comments bc, blog_message bm
WHERE bm.MessageId = bc.MessageId
GROUP BY bm.MessageId
If you want the Author and AddedDate just add it to the SELECT statement (i.e. SELECT bm.MessageId, count(bc.CommentId) as comment_count, bm.AddedDate, bm.Author).
Try the following
SELECT
bm.MessageID, Count(bc.CommentID) as Cnt, Title, Username, AddedDate
FROM blog_message bm
LEFT OUTER JOIN blog_comments bc
ON bm.MessageID = bc.MessageID
GROUP BY bm.MessageID,Title, Username, AddedDate
Related
What constraints are copied with table when we create table by using create table as select statement..?
I don't know about MySQL, but - as of Oracle - only the NOT NULL constraint. Even if there was a column designed as a primary key (which - implicitly - means that it can't be NULL), newly created table won't have that constraint.
For example:
SQL> create table test_1
2 (id number primary key,
3 name varchar2(20) not null);
Table created.
SQL> select constraint_name, constraint_Type from user_constraints where table_name = 'TEST_1';
CONSTRAINT_NAME C
-------------------- -
SYS_C009194 C --> "C"heck (NOT NULL) constraint
SYS_C009195 P --> "P"rimary key constraint
SQL> create table test_2 as select * from test_1;
Table created.
SQL> select constraint_name, constraint_Type from user_constraints where table_name = 'TEST_2';
CONSTRAINT_NAME C
-------------------- -
SYS_C009196 C --> that's the "C"heck - NOT NULL constraint
SQL> desc test_2
Name Null? Type
----------------------------------------- -------- ----------------------------
ID NUMBER
NAME NOT NULL VARCHAR2(20)
SQL>
MySQL would only preserve NOT NULL as constarint
CREATE TABLE tab1(id int AUTO_INCREMENT PRIMARY KEY)
create table tab2
(id int primary key,
col1 varchar(20) not null,
col2 int UNIQUE,
col3 int, FOREIGN KEY (col3) REFERENCES tab1(id))
CREATE TABLE tab3 AS SELECT * FROM tab2
Records: 0 Duplicates: 0 Warnings: 0
SHOW CREATE TABLE tab3
Table
Create Table
tab3
CREATE TABLE `tab3` ( `id` int NOT NULL, `col1` varchar(20) NOT NULL, `col2` int DEFAULT NULL, `col3` int DEFAULT NULL) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci
fiddle
I have the following MARIADB code. It's supposed to demonstrate:
Constructing tables using sequences for incrementing the ID.
Using a temporary table+join to INSERT data into a table, while incrementing the ID.
Procedure:
Sequence S1 and table T1 are created. T1_ID is incremented with S1
Sequence S2 and table T2 are created. T2_ID is incremented with S2
Table T1 is filled with data. All is fine.
Temporary table TEMP_T2 is created and filled with data. No ID in this table. Column T1_NAME is a cross reference to SHORT_NAME in table T1.
The T1_ID is introduced into table TEMP_T2 with a join. The result of this SELECT is inserted into T2. Here, the sequence S2 should auto-increment T2_ID.
For some reason, at the end, T2 looks like this:
T2_ID|T1_ID|NAME|
-----+-----+----+
2| 1|y |
4| 2|x |
6| 2|z |
Why was T2_ID double-incremented?
Thanks!
USE DB1;
SET FOREIGN_KEY_CHECKS = 0;
DROP SEQUENCE IF EXISTS `S2`;
DROP SEQUENCE IF EXISTS `S1`;
DROP TABLE IF EXISTS `T2`;
DROP TABLE IF EXISTS `T1`;
-- Create sequence S1 and able T1
CREATE SEQUENCE `S1` start with 1 minvalue 1 maxvalue 9223372036854775806 increment by 1 cache 1000 nocycle ENGINE=InnoDB;
SELECT SETVAL(`S1`, 1, 0);
CREATE TABLE `T1` (
`T1_ID` tinyint(4) NOT NULL DEFAULT nextval(`S1`),
`SHORT_NAME` varchar(10) NOT NULL,
PRIMARY KEY (`T1_ID`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3;
-- Create sequence T2 and table T2
CREATE SEQUENCE `S2` start with 1 minvalue 1 maxvalue 9223372036854775806 increment by 1 cache 1000 nocycle ENGINE=InnoDB;
SELECT SETVAL(`S2`, 1, 0);
CREATE TABLE `T2` (
`T2_ID` int(11) NOT NULL DEFAULT nextval(`S2`),
`T1_ID` int(11) DEFAULT NULL,
`NAME` varchar(100) DEFAULT NULL COLLATE 'utf8mb3_bin',
PRIMARY KEY (`T2_ID`),
UNIQUE KEY `T2_NAME_UN` (`NAME`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3;
-- Load data into T1
DELETE FROM T1;
INSERT INTO T1(SHORT_NAME) VALUES
('a'),
('b'),
('c');
SELECT * FROM T1;
-- Create temporary file for joining with T1
DROP TABLE IF EXISTS `TEMP_T2`;
CREATE TEMPORARY TABLE `TEMP_T2` (
`T1_NAME` varchar(10) DEFAULT NULL,
`NAME` varchar(100) DEFAULT NULL,
UNIQUE KEY `T2_NAME_UN` (`NAME`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3;
DELETE FROM TEMP_T2 ;
-- Insert data into the temporary table
INSERT INTO TEMP_T2(T1_NAME,NAME) VALUES
('b','x'),
('a','y'),
('b','z');
SELECT * FROM TEMP_T2;
# Do a join with TEMP_T2 x T1 and insert into T2
INSERT INTO T2(T1_ID,NAME)
SELECT
t1.T1_ID ,
t2.NAME
FROM TEMP_T2 AS t2
INNER JOIN T1 AS t1
ON t2.T1_NAME =t1.SHORT_NAME ;
SELECT * FROM T2;
Thanks for the responses.
I'm using SEQUENCE rather than AUTO_INCREMENT because I was told that it is the more modern way. It also enables retrieving the last ID of any specific table.
It's strange that this should be a bug. It seems like really basic functionality. But so it is...
I've found this as a reported existing bug MDEV-29540 in INSERT ... SELECT as it pertains to sequences in default values of columns.
Because this bug is reported and fix, this problem is/will not occur in the 10.3.37, 10.4.27, 10.5.18, 10.6.11, 10.7.7, 10.8.6, 10.9.4, 10.10.2, 10.11.1 and later versions.
I need to retrieve events from table, with skills requirements and user engagements and skills.
For a project, I have :
an users table
a skills table with inheritance from others skills
an users_skills table with skills of users
an events table
an events_skills table with the quantity of a required skills for the events
an events_users table with users engagements on events
CREATE TABLE `users` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT PRIMARY KEY,
`name` char(32) NOT NULL
);
CREATE TABLE `skills` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT PRIMARY KEY,
`name` char(64) NOT NULL,
`parent_id` int(11) unsigned DEFAULT NULL,
FOREIGN KEY (`parent_id`) REFERENCES `skills` (`id`)
);
CREATE TABLE `users_skills` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT PRIMARY KEY,
`user_id` int(11) unsigned NOT NULL,
`skill_id` int(11) unsigned NOT NULL,
FOREIGN KEY (`user_id`) REFERENCES `users` (`id`),
FOREIGN KEY (`skill_id`) REFERENCES `skills` (`id`)
);
CREATE TABLE `events` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT PRIMARY KEY,
`name` char(64) NOT NULL
);
CREATE TABLE `events_skills` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT PRIMARY KEY,
`event_id` int(11) unsigned NOT NULL,
`skill_id` int(11) unsigned NOT NULL,
`quantity` smallint unsigned NOT NULL,
FOREIGN KEY (`event_id`) REFERENCES `events` (`id`),
FOREIGN KEY (`skill_id`) REFERENCES `skills` (`id`)
);
CREATE TABLE `events_users` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT PRIMARY KEY,
`event_id` int(11) unsigned NOT NULL,
`user_id` int(11) unsigned NOT NULL,
FOREIGN KEY (`event_id`) REFERENCES `events` (`id`),
FOREIGN KEY (`user_id`) REFERENCES `users` (`id`)
);
I want to retrieve all events, with skills requirments and users participation.
My first idea was to use LEFT JOIN :
SELECT e.id, e.name, es.skill_id, s.name skill_name, es.quantity,
eu.user_id, u.name user_name, us.skill_id user_skill_id,
uss.name user_skill_name
FROM events e
LEFT JOIN events_skills es ON es.event_id = e.id
LEFT JOIN skills s ON s.id = es.skill_id
LEFT JOIN events_users eu ON eu.event_id = e.id
LEFT JOIN users u ON u.id = eu.user_id
LEFT JOIN users_skills us ON us.user_id = u.id
LEFT JOIN skills uss ON uss.id = us.skill_id;
id name skill_id skill_name quantity user_id user_name user_skill_id user_skill_name
1 eve1 2 ski2 3 1 use1 2 ski2
1 eve1 3 ski2-2 1 1 use1 2 ski2
1 eve1 2 ski2 3 2 use2 NULL NULL
1 eve1 3 ski2-2 1 2 use2 NULL NULL
2 eve2 NULL NULL NULL NULL NULL NULL NULL
2 differents events, second without users and skills. First, with 2 users, first with one skills, seconds without skills, and finally, two skills requirements.
It work "fine", but it's verry ugly, and I think it can be very slow if an event or an user has too many skills.
Also, each event has a lot of lines, and it's difficult to sort them (if I want to display only 20 events...).
To improve, I think I can load all skills separately and remove the two LEFT JOIN for table skills.
But, can I merge all skills and quantity in one column, and users in others ? Did you have betters solutions/improvements ?
id name skills users
1 eve1 2,3;3,1 1,2;2,NULL
2 eve2 NULL NULL
Thanks for your help.
Another way to do what Thorsten suggested:
select e.*,
( SELECT group_concat(skill_id order by skill_id separator ',')
from events_skills
WHERE event_id = e.id
) AS skills,
( SELECT group_concat(user_id order by user_id separator ',' )
from events_users
WHERE event_id = e.id
) AS users
from events e
order by e.id;
Each subquery needs an extra join to get the "name" of the skill and user instead of the "id".
May I suggest you use the name of the skill as its id.
When you have a many-many mapping table, be sure to use the pair of ids as the PRIMARY KEY and have an INDEX in the opposite order. And don't have an AUTO_INCREMENT. Details: http://mysql.rjweb.org/doc.php/index_cookbook_mysql#many_to_many_mapping_table
A result with skills and users as comma-separated strings is exactly how I would do this, too. Use GROUP_CONCAT for this.
select e.*, s.skills, u.users
from events e
left join
(
select event_id, group_concat(skill_id order by skill_id separator ',') as skills
from events_skills
group by event_id
) s on s.event_id = e.id
left join
(
select event_id, group_concat(user_id order by user_id separator ',') as users
from events_users
group by event_id
) u on u.event_id = e.id
order by e.id;
I have following tables in my DB
CREATE TABLE [author_details] (
[_id] INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
[name] TEXT NOT NULL,
[surname] TEXT NOT NULL,
[middle_name] TEXT NULL
);
CREATE TABLE [authors] (
[_id] INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
[book_id] INTEGER NOT NULL,
[author_id] INTEGER NOT NULL
);
CREATE TABLE [books] (
[_id] INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
[title] TEXT NOT NULL,
[publisher_id] INTEGER NOT NULL,
[isbn] VARCHAR(10) UNIQUE NULL,
[ean] VARCHAR(13) UNIQUE NULL,
[pages] INTEGER DEFAULT '0' NULL,
[year] INTEGER NOT NULL,
[edition] TEXT NULL
);
CREATE TABLE [publishers] (
[_id] INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
[name] TEXT NOT NULL
);
I want a list of all books with details, I've used following query:
SELECT b.title,b.isbn,b.ean,b.year,b.pages,b.edition,
CASE
WHEN ad.middle_name IS NULL
THEN ad.name||" "||ad.surname
ELSE ad.name||" "||ad.middle_name||" "||ad.surname
END AS author, p.name
FROM books AS b, authors AS a, author_details AS ad, publishers AS p
INNER JOIN authors, author_details, publishers ON b._id=a.book_id AND ad._id=a.author_id AND b.publisher_id=p._id
GROUP BY b._id
It returns All books but only one author for books with multiple authors. How to write the query to get all authors per book?
To get the values from all records in a group, you have to use the group_concat function:
SELECT b.title,b.isbn,b.ean,b.year,b.pages,b.edition,
group_concat(CASE
...
END) AS author, p.name
FROM ...
Additionally, you need to use the correct join syntax.
In your query, you are joining every table twice, which results in lots up duplicate records.
There are two equivalent syntaxes for joins.
Either use a plain list of tables, and WHERE:
...
FROM books AS b,
authors AS a,
author_details AS ad,
publishers AS p
WHERE b._id = a.book_id
AND a.author_id = ad._id
AND b.publisher_id = p._id
...
or use the JOIN operator for each join, with a join condition for each join:
...
FROM books AS b
JOIN authors AS a ON b._id = a.book_id
JOIN author_details AS ad ON a.author_id = ad._id
JOIN publishers AS p ON b.publisher_id = p._id
...
Try to use group_concat():
SELECT b.title,b.isbn,b.ean,b.year,b.pages,b.edition,
GROUP_CONCAT(CASE
WHEN ad.middle_name IS NULL
THEN ad.name||" "||ad.surname
ELSE ad.name||" "||ad.middle_name||" "||ad.surname
END) AS author,
p.name
FROM
.........
I'm having difficulty joining data from three tables.
This is an anonymous shopping cart for a real estate company. The inmuebles table holds the details of the properties.
If some wants to have a viewing I create a record in the temppropertylist table using their asp.net sessionid, and in the
anonymouscart table I add a record of the property they are interested in.
I'm showing this in a gridview control so when I rebind it I need a query that pulls the information from the three tables,
showing all the property data, and whether or not each property has been selected for viewing. To do that it's sufficient
to have either the propertyid or a null from the anonymouscart to be joined to each record in the inmuebles table as I can use it to toggle a checkbox.
What I found was my original query was pulling information from the anonymous cart for all of the related records in the
temppropertylist table so I'm trying to filter that using the sessionid in the join but it now only shows inmuebles records where there
is a related record in anonymouscart.
I've read every listing I could on Stackoverflow but I can't get my head around what I'm doing wrong
CREATE TABLE [dbo].[anonymouscart](
[Id] [int] IDENTITY(1,1) NOT NULL,
[temppropertylist_id] [int] NOT NULL,
[timestamp] [datetime2](7) NOT NULL,
[propertyid] [int] NULL
) ON [PRIMARY]
Id temppropertylist_id timestamp propertyid
40 38 2013-09-24 08:24:00.0772687 2
39 37 2013-09-24 08:03:56.1163987 1
CREATE TABLE [dbo].[temppropertylist](
[ID] [int] IDENTITY(1,1) NOT NULL,
[sessionID] [nvarchar](50) NULL,
[userID] [int] NULL,
[timestamp] [datetime2](7) NOT NULL
) ON [PRIMARY]
ID sessionID userID timestamp
37 jgyo5i4vne35bcolow23je1q NULL 2013-09-24 08:02:29.1129679
38 uuoawmav4jhi3hy3g3v4vr3o NULL 2013-09-24 08:23:58.8604375
CREATE TABLE [dbo].[Inmuebles](
[Id] [int] IDENTITY(1,1) NOT NULL,
[Title] [nvarchar](99) NULL,
[tipodemanda] [nvarchar](10) NULL,
[Descripcioni] [nvarchar](max) NULL,
[PrecioVenta] [int] NULL,
[Imagen] [nvarchar](255) NULL,
[onhold] [bit] NOT NULL,
) ON [PRIMARY]
My query:
SELECT inmuebles.title
, inmuebles.Descripcioni
, inmuebles.ID
, inmuebles.PrecioVenta
, inmuebles.imagen
, MIN(anonymouscart.propertyID) AS propertyID
FROM inmuebles
FULL OUTER JOIN anonymouscart ON Inmuebles.ID = anonymouscart.propertyID
FULL OUTER JOIN temppropertylist ON anonymouscart.temppropertylist_id = temppropertylist.ID
AND (temppropertylist.sessionid = 'uuoawmav4jhi3hy3g3v4vr3o')
WHERE tipodemanda = 'venta'
AND onhold = 0
GROUP BY
inmuebles.title
, inmuebles.Descripcioni
, inmuebles.ID
, inmuebles.PrecioVenta
, inmuebles.imagen
This returns:
title Descripcioni id PrecioVenta imagen propertyid
'Two for One' 'This is a ....' 2 110000 NULL 2
But what I want is all the records from the inmuebles table with nulls for propertyid
This the data from the inmuebles table:
title Descripcioni id PrecioVenta imagen onhold tipodemanda
'Casa Bodega', 'This is a...', 1, 11000, '1_27152256.jpg',0, 'venta'
'Two for One', 'This is a...', 2, 110000, NULL, 0, 'venta'
First of all, it is necessary to use a derived table and only after that join the Inmuebles table
SELECT inmuebles.title
, inmuebles.Descripcioni
, inmuebles.ID
, inmuebles.PrecioVenta
, inmuebles.imagen
, MIN(x.propertyID) AS propertyID
FROM inmuebles
LEFT JOIN (SELECT anonymouscart.propertyID
FROM anonymouscart JOIN temppropertylist
ON anonymouscart.temppropertylist_id = temppropertylist.ID
AND temppropertylist.sessionid = 'uuoawmav4jhi3hy3g3v4vr3o'
) x ON Inmuebles.ID = x.propertyID
WHERE tipodemanda = 'venta' AND onhold = 0
GROUP BY
inmuebles.title
, inmuebles.Descripcioni
, inmuebles.ID
, inmuebles.PrecioVenta
, inmuebles.imagen